Skip to content

Commit

Permalink
Merge pull request #14 from mynk2611/main
Browse files Browse the repository at this point in the history
fixed all the issue related to focus trap
  • Loading branch information
jhancock532 authored Dec 28, 2024
2 parents e8ca5ed + 09805d8 commit f448a37
Showing 1 changed file with 58 additions and 4 deletions.
62 changes: 58 additions & 4 deletions src/components/Header/Header.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,73 @@
import React, { useState } from 'react';
import React, { useState, useEffect, useRef } from 'react';
import Link from 'next/link';

import styles from './Header.module.scss';

export const Header = () => {
const [isMenuOpen, setIsMenuOpen] = useState(false);
const menuRef = useRef<HTMLDivElement | null>(null);
const closeButtonRef = useRef<HTMLButtonElement | null>(null);
const firstFocusableElementRef = useRef(null);

const toggleMenu = () => {
setIsMenuOpen(!isMenuOpen);
setIsMenuOpen((prev) => !prev);
};

// Handle trapping focus
useEffect(() => {
const handleKeyDown = (e: KeyboardEvent) => {
if (isMenuOpen) {
const focusableElements =
menuRef.current?.querySelectorAll<HTMLElement>(
'a, button',
) || [];
const firstElement = focusableElements[0];
const lastElement =
focusableElements[focusableElements.length - 1];

if (e.key === 'Tab') {
// Shift + Tab (backward)
if (e.shiftKey && document.activeElement === firstElement) {
e.preventDefault();
lastElement?.focus(); // Loop focus to last element
}
// Tab (forward)
else if (
!e.shiftKey &&
document.activeElement === lastElement
) {
e.preventDefault();
firstElement?.focus(); // Loop focus to first element
}
} else if (e.key === 'Escape') {
// Close menu on Escape key
setIsMenuOpen(false);
}
}
};

if (isMenuOpen) {
document.addEventListener('keydown', handleKeyDown);
// Focus on the close button when menu opens
closeButtonRef.current?.focus();
} else {
document.removeEventListener('keydown', handleKeyDown);
}

return () => document.removeEventListener('keydown', handleKeyDown);
}, [isMenuOpen]);
return (
<header className={styles.container}>
<div></div>
<div>
<nav
className={`${styles.nav} ${isMenuOpen ? styles.navOpen : ''}`}
className={`${styles.nav} ${
isMenuOpen ? styles.navOpen : ''
}`}
ref={menuRef}
>
<button
ref={closeButtonRef}
className={styles.menuButton}
onClick={toggleMenu}
aria-label="Close menu"
Expand Down Expand Up @@ -48,7 +98,11 @@ export const Header = () => {
</button>
<ul>
<li className={styles.navItem}>
<Link href="/" className={styles.link}>
<Link
href="/"
className={styles.link}
ref={firstFocusableElementRef} // First focusable element
>
Home
</Link>
</li>
Expand Down

0 comments on commit f448a37

Please sign in to comment.