The code examples I have seen so far use libraries like JQuery and react-focus-lock https://www.npmjs.com/package/react-focus-lock I would really appreciate a simple example of two buttons in a modal such that you can't focus elements outside the modal by tabbing out.
            Asked
            
        
        
            Active
            
        
            Viewed 882 times
        
    1 Answers
0
            
            
        I'm using following component to wrap the content where focus has to be trapped:
import { useRef, useEffect } from "react";
type Props = {
    children: Array<JSX.Element | null>;
};
export const FocusTrap = (props: Props) => {
    const ref = useRef<HTMLSpanElement>(null);
    useEffect(() => {
        let firstElement: (HTMLElement | undefined);
        let lastElement: (HTMLElement | undefined);
        if (ref.current != null)
            for (const element of ref.current.querySelectorAll<HTMLElement>("[tabindex]"))
                considerElement(element);
        firstElement?.addEventListener("keydown", handleKeyOnFirst);
        lastElement?.addEventListener("keydown", handleKeyOnLast);
        return () => {
            firstElement?.removeEventListener("keydown", handleKeyOnFirst);
            lastElement?.removeEventListener("keydown", handleKeyOnLast);
        };
        function considerElement(element: HTMLElement) {
            // @ts-ignore
            if (!element.checkVisibility()) return;
            if (firstElement === undefined) firstElement = element;
            else lastElement = element;
        }
        function handleKeyOnFirst(event: KeyboardEvent) {
            if (event.key !== "Tab" || !event.shiftKey) return;
            event.preventDefault();
            lastElement?.focus();
        }
        function handleKeyOnLast(event: KeyboardEvent) {
            if (event.key !== "Tab" || event.shiftKey) return;
            event.preventDefault();
            firstElement?.focus();
        }
    }, [props.children]);
    return <span ref={ref}>{props.children}</span>;
};
Used like this:
<FocusTrap>
    <ModalOrOtherContentToTrapFocus/>
</FocusTrap>
The trap component scans underlying content finding first and last visible elements with tabIndex attribute and overrides Tab/Shift+Tab behavior for them.
Be aware, that as of writing element.checkVisibility() function is only available in Chrome. Related thread on SO: Check if element is visible in DOM.
 
    
    
        Elringus
        
- 539
- 6
- 12
