Skip to content

Commit

Permalink
Merge pull request #4544 from Sage/FE-4422-multiple-dialogs-focus-tra…
Browse files Browse the repository at this point in the history
…p-fix

feat(focus-trap): add flag to trigger refocus of either last focused element first element FE-4422
  • Loading branch information
edleeks87 authored Nov 18, 2021
2 parents 023ac23 + 5b9c5f7 commit 83c94e0
Show file tree
Hide file tree
Showing 5 changed files with 283 additions and 68 deletions.
41 changes: 40 additions & 1 deletion src/__internal__/focus-trap/focus-trap.component.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,9 @@ const FocusTrap = ({
const [focusableElements, setFocusableElements] = useState();
const [firstElement, setFirstElement] = useState();
const [lastElement, setLastElement] = useState();
const { isAnimationComplete } = useContext(ModalContext);
const [currentFocusedElement, setCurrentFocusedElement] = useState();
const { isAnimationComplete, triggerRefocusFlag } = useContext(ModalContext);

const hasNewInputs = useCallback(
(candidate) => {
if (!focusableElements || candidate.length !== focusableElements.length) {
Expand Down Expand Up @@ -129,6 +131,43 @@ const FocusTrap = ({
};
}, [firstElement, lastElement, focusableElements, bespokeTrap]);

const updateCurrentFocusedElement = useCallback(() => {
const element = focusableElements?.find(
(el) => el === document.activeElement
);

if (element) {
setCurrentFocusedElement(element);
}
}, [focusableElements]);

useEffect(() => {
document.addEventListener("focusin", updateCurrentFocusedElement);

return () => {
document.removeEventListener("focusin", updateCurrentFocusedElement);
};
}, [updateCurrentFocusedElement]);

const refocusTrap = useCallback(() => {
/* istanbul ignore else */
if (
currentFocusedElement &&
!currentFocusedElement.hasAttribute("disabled")
) {
// the trap breaks if it tries to refocus a disabled element
setElementFocus(currentFocusedElement);
} else if (firstElement) {
setElementFocus(firstElement);
}
}, [currentFocusedElement, firstElement]);

useEffect(() => {
if (triggerRefocusFlag) {
refocusTrap();
}
}, [triggerRefocusFlag, refocusTrap]);

return <div ref={trapRef}>{children}</div>;
};

Expand Down
Loading

0 comments on commit 83c94e0

Please sign in to comment.