Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Writing flow: Fix focus loss on toolbar return when last focus element isn't found #54443

Open
wants to merge 5 commits into
base: trunk
Choose a base branch
from
Open
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,10 @@ import { isInSameBlock, isInsideRootBlock } from '../../utils/dom';

export default function useTabNav() {
const container = useRef();
const lastFocus = useRef();
const lastBlock = useRef();
const focusCaptureBeforeRef = useRef();
const focusCaptureAfterRef = useRef();
const lastFocus = useRef();
const { hasMultiSelection, getSelectedBlockClientId, getBlockCount } =
useSelect( blockEditorStore );
const { setNavigationMode } = useDispatch( blockEditorStore );
Expand All @@ -40,7 +41,31 @@ export default function useTabNav() {
} else if ( hasMultiSelection() ) {
container.current.focus();
} else if ( getSelectedBlockClientId() ) {
lastFocus.current.focus();
// If last focus position matches last block, this likely means we're on the last block wrapper. Let's try to find a better place to focus before defaulting to the wrapper.
if ( lastBlock.current !== lastFocus.current ) {
// Try to focus the last element which had focus.
lastFocus.current.focus();
// Check to see if focus worked.
if (
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is ugly but necessary.

lastFocus.current.ownerDocument.activeElement ===
lastFocus.current
) {
// Looks like yes, return early.
return;
}
}
// Last element focus did not work. Now try to find the first tabbable in the last block to focus.
const firstBlockTabbable = focus.tabbable.findNext(
lastBlock.current
);
// Check to ensure tabbable is inside the last block and that it is a form element.
if ( isInsideRootBlock( lastBlock.current, firstBlockTabbable ) ) {
// Focus the found tabbable in the last block.
firstBlockTabbable.focus();
} else {
// Focus the last block wrapper if no tabbable was found.
lastBlock.current.focus();
}
} else {
setNavigationMode( true );

Expand Down Expand Up @@ -158,7 +183,10 @@ export default function useTabNav() {
}

function onFocusOut( event ) {
// Capture the last element with focus.
lastFocus.current = event.target;
// Capture the last known block before focus leaves writing flow.
lastBlock.current = event.target.closest( '[data-block]' );

const { ownerDocument } = node;

Expand Down
Loading