import { useEffect, RefObject } from 'react'; /** * Hook to trap focus within a container element * Useful for modals, drawers, and overlays * * @param containerRef - Reference to the container element * @param isActive - Whether the focus trap is active */ export function useFocusTrap( containerRef: RefObject, isActive: boolean ) { useEffect(() => { if (!isActive || !containerRef.current) return; const container = containerRef.current; // Get all focusable elements const focusableElements = container.querySelectorAll( 'a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])' ); if (focusableElements.length === 0) return; const firstElement = focusableElements[0]; const lastElement = focusableElements[focusableElements.length - 1]; // Store the element that had focus before the trap const previouslyFocusedElement = document.activeElement as HTMLElement; // Focus the first element firstElement.focus(); const handleTabKey = (e: KeyboardEvent) => { if (e.key !== 'Tab') return; if (e.shiftKey) { // Shift + Tab if (document.activeElement === firstElement) { e.preventDefault(); lastElement.focus(); } } else { // Tab if (document.activeElement === lastElement) { e.preventDefault(); firstElement.focus(); } } }; container.addEventListener('keydown', handleTabKey); // Cleanup: restore focus to previously focused element return () => { container.removeEventListener('keydown', handleTabKey); if (previouslyFocusedElement) { previouslyFocusedElement.focus(); } }; }, [containerRef, isActive]); }