-
Notifications
You must be signed in to change notification settings - Fork 953
Expand file tree
/
Copy pathhandle-banner-tab-navigation.js
More file actions
34 lines (31 loc) · 1.36 KB
/
handle-banner-tab-navigation.js
File metadata and controls
34 lines (31 loc) · 1.36 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
import { focus } from "@wordpress/dom";
/**
* Keydown handler that keeps the inline banner reachable via Tab inside the Gutenberg
* writing flow. Gutenberg's useTabNav hook intercepts Tab in the bubble phase and
* redirects focus to sentinel divs when the next tabbable element is not inside the
* same [data-block] wrapper. Because the banner sits outside any real block, it is
* normally skipped. This handler is meant to be attached in the capture phase so it
* runs before Gutenberg; once it calls preventDefault(), Gutenberg's early-return guard
* fires and leaves focus alone.
*
* @param {HTMLElement} bannerEl The banner wrapper element.
* @param {KeyboardEvent} event The keydown event.
* @returns {void}
*/
// eslint-disable-next-line complexity
export function handleBannerTabNavigation( bannerEl, event ) {
if ( event.defaultPrevented || event.keyCode !== 9 || ! bannerEl ) {
return;
}
const findSibling = event.shiftKey ? focus.tabbable.findPrevious : focus.tabbable.findNext;
const next = findSibling( event.target );
if ( ! next ) {
return;
}
// Intercept only when Tab or Shift+Tab crosses the banner boundary (entering or leaving).
// Intra-banner navigation is already handled by Gutenberg via the data-block attribute.
if ( bannerEl.contains( event.target ) !== bannerEl.contains( next ) ) {
event.preventDefault();
next.focus();
}
}