Skip to content

Commit

Permalink
ignore previousElement in wrap focus calculation.
Browse files Browse the repository at this point in the history
If a consumer manually calls `.focus()`, `relatedTarget` won't be set on the focus event, which was causing problems where some people would force focus around in a modal on tab presses, only to see focus attempt to "wrap" back to the beginning of the modal from the middle of it.
  • Loading branch information
faultyserver committed May 16, 2020
1 parent 1c07dc1 commit fb60395
Showing 1 changed file with 3 additions and 5 deletions.
8 changes: 3 additions & 5 deletions src/useFocusLock.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -93,15 +93,15 @@ function createFocusWalker(root: HTMLElement) {
});
}

function wrapFocus(root: HTMLElement, target: Element, previousElement?: Element | null) {
function wrapFocus(root: HTMLElement, target: Element) {
const walker = createFocusWalker(root);
const position = target.compareDocumentPosition(root);
let wrappedTarget = null;

// previousElement would be null if a) there wasn't an element focused before
// or b) focus came into the document from outside. In either case, it can be
// treated as a reset point to bring focus back into the layer.
if (position & Node.DOCUMENT_POSITION_PRECEDING || previousElement == null) {
if (position & Node.DOCUMENT_POSITION_PRECEDING) {
wrappedTarget = walker.firstChild() as HTMLElement | null;
} else if (position & Node.DOCUMENT_POSITION_FOLLOWING) {
wrappedTarget = walker.lastChild() as HTMLElement | null;
Expand Down Expand Up @@ -162,11 +162,9 @@ export function useFocusLock(
if (root == null) return;

const newFocusElement = (event.target as Element | null) || document.body;
const prevFocusElement = event.relatedTarget as Element | null;

if (!root.contains(newFocusElement)) {
event.preventDefault();
wrapFocus(root, newFocusElement, prevFocusElement);
wrapFocus(root, newFocusElement);
}
}

Expand Down

0 comments on commit fb60395

Please sign in to comment.