-
Notifications
You must be signed in to change notification settings - Fork 366
Expand file tree
/
Copy pathuseFocusTrap.js
More file actions
41 lines (34 loc) · 1.2 KB
/
useFocusTrap.js
File metadata and controls
41 lines (34 loc) · 1.2 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
35
36
37
38
39
40
41
import { useEffect, useRef } from 'react';
/**
* POC: GSoC 2026 - Keyboard Navigation & WCAG Compliance
* Implements a strict Focus Trap ref to prevent users from tabbing out
* of critical UI layers like EmojiPickers or Modals.
*/
export const useFocusTrap = (isActive) => {
const containerRef = useRef(null);
useEffect(() => {
if (!isActive) return;
const handleKeyDown = (event) => {
if (event.key !== 'Tab') return;
const focusableElements = containerRef.current.querySelectorAll(
'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
);
const firstElement = focusableElements[0];
const lastElement = focusableElements[focusableElements.length - 1];
if (event.shiftKey) {
if (document.activeElement === firstElement) {
lastElement.focus();
event.preventDefault();
}
} else {
if (document.activeElement === lastElement) {
firstElement.focus();
event.preventDefault();
}
}
};
window.addEventListener('keydown', handleKeyDown);
return () => window.removeEventListener('keydown', handleKeyDown);
}, [isActive]);
return containerRef;
};