Skip to content

Commit ab3623d

Browse files
focus trap
1 parent 777af23 commit ab3623d

File tree

2 files changed

+45
-0
lines changed

2 files changed

+45
-0
lines changed

src/app/page.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
1+
'use client'
2+
13
import Feed from '@/components/feed/Feed'
24
import Footer from '@/components/footer/Footer'
35
import Navigation from '@/components/navigation/Navigation'
6+
import { useFocusTrap } from '@/hooks/useFocusTrap'
47

58
export default function Home() {
9+
useFocusTrap()
10+
611
return (
712
<div className="min-h-svh flex flex-col items-center justify-start bg-gradient-to-b from-stone-700 to-stone-800">
813
<Navigation />

src/hooks/useFocusTrap.ts

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
'use client'
2+
3+
import { useEffect } from 'react'
4+
5+
export const useFocusTrap = () => {
6+
useEffect(() => {
7+
const focusTrap = (e: KeyboardEvent) => {
8+
if (e.key !== 'Tab') {
9+
return
10+
}
11+
12+
const focusableElements = (
13+
Array.from(
14+
document.querySelectorAll('a, button')
15+
) as HTMLButtonElement[]
16+
).filter((item) => !item.disabled)
17+
18+
const firstFocusableElement = focusableElements[0]
19+
const lastFocusableElement = focusableElements.at(-1)
20+
21+
if (e.shiftKey) {
22+
if (document.activeElement === firstFocusableElement) {
23+
e.preventDefault()
24+
lastFocusableElement?.focus()
25+
}
26+
} else {
27+
if (document.activeElement === lastFocusableElement) {
28+
e.preventDefault()
29+
firstFocusableElement?.focus()
30+
}
31+
}
32+
}
33+
34+
document.addEventListener('keydown', focusTrap)
35+
36+
return () => {
37+
document.removeEventListener('keydown', focusTrap)
38+
}
39+
})
40+
}

0 commit comments

Comments
 (0)