Skip to main content

useFocusTrap

Location: src/hooks/useFocusTrap.js

Overview

Traps keyboard focus within a container element, ensuring that Tab and Shift+Tab cycling stays within the container. This is essential for accessibility in modals, dialogs, and drawers, preventing keyboard users from tabbing to elements behind the overlay.

When activated, the hook automatically focuses the first focusable element in the container.

Signature

function useFocusTrap(isActive?: boolean): React.RefObject<HTMLElement>

Parameters

ParameterTypeRequiredDefaultDescription
isActivebooleanNotrueWhether the focus trap is active. Set to false to disable trapping.

Return Value

TypeDescription
React.RefObject<HTMLElement>A ref to attach to the container element that should trap focus

Focusable Elements

The hook considers these elements as focusable:

  • button:not([disabled])
  • input:not([disabled])
  • textarea:not([disabled])
  • select:not([disabled])
  • a[href]
  • [tabindex]:not([tabindex="-1"])

Usage

import { useFocusTrap } from '../hooks/useFocusTrap';

function Modal({ isOpen, onClose, children }) {
const trapRef = useFocusTrap(isOpen);

if (!isOpen) return null;

return (
<div className="modal-overlay" onClick={onClose}>
<div ref={trapRef} className="modal-content" onClick={(e) => e.stopPropagation()}>
{children}
<button onClick={onClose}>Close</button>
</div>
</div>
);
}

Behavior

  1. When isActive becomes true, the first focusable element inside the container receives focus.
  2. Pressing Tab on the last focusable element wraps focus to the first.
  3. Pressing Shift+Tab on the first focusable element wraps focus to the last.
  4. The keydown listener is attached to the container element and cleaned up when the trap is deactivated or the component unmounts.

Notes

  • The hook dynamically queries focusable elements on each Tab keypress, so it handles elements that appear or disappear after mount.
  • If the container has no focusable elements, Tab keypresses are not intercepted.
  • Pair this with useEscapeKey for complete modal keyboard accessibility.

Last updated: 2026-02-07