focus trap hook

This commit is contained in:
2025-12-25 19:42:41 +02:00
parent 9a58f5895b
commit 542b3eb6b3
+38
View File
@@ -0,0 +1,38 @@
import { useEffect, useRef } from 'react'
export function useFocusTrap(active: boolean) {
const ref = useRef<HTMLDivElement>(null)
const previousFocus = useRef<HTMLElement | null>(null)
useEffect(() => {
if (!active || !ref.current) return
const activeElement = document.activeElement
previousFocus.current = activeElement instanceof HTMLElement ? activeElement : null
const container = ref.current
const sel = 'button:not([disabled]), [href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])'
const initial = container.querySelectorAll<HTMLElement>(sel)
if (initial.length > 0) initial[0].focus()
const handleKeyDown = (e: KeyboardEvent) => {
if (e.key !== 'Tab') return
const focusable = container.querySelectorAll<HTMLElement>(sel)
if (focusable.length === 0) return
const first = focusable[0]
const last = focusable[focusable.length - 1]
if (e.shiftKey && document.activeElement === first) {
e.preventDefault(); last.focus()
} else if (!e.shiftKey && document.activeElement === last) {
e.preventDefault(); first.focus()
}
}
container.addEventListener('keydown', handleKeyDown)
return () => {
container.removeEventListener('keydown', handleKeyDown)
previousFocus.current?.focus()
}
}, [active])
return ref
}