Skip to main content
FocusScope is a component that manages focus containment and focus trapping. It’s commonly used in modal dialogs, popovers, and other overlay components to ensure keyboard focus remains within a specific area.

Installation

Component

FocusScope

Props

boolean
When true, tabbing from the last focusable element will focus the first element, and shift+tab from the first element will focus the last. Creates a circular focus loop.Default: false
boolean
When true, focus cannot escape the scope via keyboard, pointer, or programmatic focus. This creates a “focus trap” essential for modal dialogs.Default: false
(event: Event) => void
Event handler called when the component mounts and attempts to auto-focus. Call event.preventDefault() to prevent the default auto-focus behavior.
(event: Event) => void
Event handler called when the component unmounts and attempts to restore focus. Call event.preventDefault() to prevent restoring focus to the previously focused element.

Usage

Basic Modal Dialog

Focus Loop without Trapping

Prevent Auto-focus

Prevent Focus Restore

Nested Focus Scopes

Custom Focus Priority

Form with Focus Management

Behavior

Auto-focus on Mount

By default, FocusScope will:
  1. Remember the currently focused element
  2. Focus the first focusable element inside the scope
  3. Can be prevented with onMountAutoFocus

Auto-focus on Unmount

By default, FocusScope will:
  1. Restore focus to the element that was focused before mounting
  2. Can be prevented with onUnmountAutoFocus

Focus Trapping

When trapped={true}:
  • Tab and Shift+Tab are contained within the scope
  • Clicking outside cannot move focus out
  • Programmatic focus changes to elements outside are prevented

Focus Looping

When loop={true}:
  • Tab from the last element focuses the first element
  • Shift+Tab from the first element focuses the last element
  • Works independently of trapping

Accessibility

Focus trapping is essential for modal dialogs to meet WCAG 2.1 success criterion 2.4.3 (Focus Order). It ensures keyboard users can navigate the modal without accidentally leaving it.
Always provide a clear way to dismiss focus-trapped components (like a close button or Escape key handler) to prevent keyboard users from getting stuck.

Notes

FocusScope works by listening to focus events and programmatically managing focus when needed. It respects native browser behavior while adding focus containment.
The component uses focusScope.pause() and focusScope.resume() internally to temporarily disable focus trapping when needed. This is useful for nested focus scopes.
Focus guards (from @radix-ui/react-focus-guards) may be needed alongside FocusScope to ensure focus events are properly captured in all scenarios.