React hooks and components for accessible focus management including FocusScope for focus containment, FocusRing for visual focus indicators, and utilities for focus navigation and virtual focus handling.
npx @tessl/cli install tessl/npm-react-aria--focus@3.21.0React Aria Focus provides accessible focus management hooks and components for React applications. It includes comprehensive focus containment, visual focus indicators, and programmatic focus navigation utilities designed to work seamlessly across different input modalities and assistive technologies.
npm install @react-aria/focusimport {
FocusScope,
FocusRing,
useFocusManager,
useFocusRing,
useHasTabbableChild,
createFocusManager,
getFocusableTreeWalker,
isElementInChildOfActiveScope,
moveVirtualFocus,
dispatchVirtualBlur,
dispatchVirtualFocus,
getVirtuallyFocusedElement,
// Re-exported from other packages
isFocusable,
FocusableProvider,
useFocusable,
focusSafely
} from "@react-aria/focus";For CommonJS:
const {
FocusScope,
FocusRing,
useFocusManager,
useFocusRing,
useHasTabbableChild,
createFocusManager,
getFocusableTreeWalker,
isElementInChildOfActiveScope,
moveVirtualFocus,
dispatchVirtualBlur,
dispatchVirtualFocus,
getVirtuallyFocusedElement,
// Re-exported from other packages
isFocusable,
FocusableProvider,
useFocusable,
focusSafely
} = require("@react-aria/focus");import React from "react";
import { FocusScope, FocusRing } from "@react-aria/focus";
function Dialog({ isOpen, onClose, children }) {
if (!isOpen) return null;
return (
<div className="dialog-backdrop">
<FocusScope contain restoreFocus autoFocus>
<div className="dialog">
<FocusRing focusRingClass="focus-visible">
<button onClick={onClose}>Close</button>
</FocusRing>
{children}
</div>
</FocusScope>
</div>
);
}
// Usage with focus manager
function CustomNavigableList() {
const focusManager = useFocusManager();
const handleKeyDown = (e: KeyboardEvent) => {
switch (e.key) {
case 'ArrowDown':
focusManager?.focusNext();
break;
case 'ArrowUp':
focusManager?.focusPrevious();
break;
}
};
return (
<FocusScope>
<div onKeyDown={handleKeyDown}>
<button>Item 1</button>
<button>Item 2</button>
<button>Item 3</button>
</div>
</FocusScope>
);
}React Aria Focus is built around several key components:
FocusScope component provides focus trapping and restoration for modal dialogs and overlaysFocusRing component and useFocusRing hook provide keyboard-only focus rings that respect user input modalityFocus containment system for modal dialogs, popover overlays, and other focus-trapped interfaces. Provides automatic focus restoration and keyboard navigation boundaries.
interface FocusScopeProps {
children: ReactNode;
contain?: boolean;
restoreFocus?: boolean;
autoFocus?: boolean;
}
function FocusScope(props: FocusScopeProps): JSX.Element;
function useFocusManager(): FocusManager | undefined;Keyboard-only focus rings that provide visual focus indicators only when users are navigating with keyboard, not mouse or touch.
interface FocusRingProps {
children: ReactElement;
focusClass?: string;
focusRingClass?: string;
within?: boolean;
isTextInput?: boolean;
autoFocus?: boolean;
}
function FocusRing(props: FocusRingProps): ReactElement;
interface FocusRingAria {
isFocused: boolean;
isFocusVisible: boolean;
focusProps: DOMAttributes;
}
function useFocusRing(props?: AriaFocusRingProps): FocusRingAria;Low-level utilities for creating custom focus managers, traversing focusable elements, and implementing keyboard navigation patterns.
interface FocusManager {
focusNext(opts?: FocusManagerOptions): FocusableElement | null;
focusPrevious(opts?: FocusManagerOptions): FocusableElement | null;
focusFirst(opts?: FocusManagerOptions): FocusableElement | null;
focusLast(opts?: FocusManagerOptions): FocusableElement | null;
}
function createFocusManager(
ref: RefObject<Element | null>,
defaultOptions?: FocusManagerOptions
): FocusManager;
function getFocusableTreeWalker(
root: Element,
opts?: FocusManagerOptions,
scope?: Element[]
): TreeWalker | ShadowTreeWalker;
function useHasTabbableChild(
ref: RefObject<Element | null>,
options?: AriaHasTabbableChildOptions
): boolean;
function isElementInChildOfActiveScope(element: Element): boolean;Support for aria-activedescendant focus patterns commonly used in comboboxes, listboxes, and other composite widgets.
function moveVirtualFocus(to: Element | null): void;
function dispatchVirtualBlur(from: Element, to: Element | null): void;
function dispatchVirtualFocus(to: Element, from: Element | null): void;
function getVirtuallyFocusedElement(document: Document): Element | null;Backward-compatible utilities re-exported from other React Aria packages for convenience.
// From @react-aria/utils
function isFocusable(element: Element): boolean;
// From @react-aria/interactions
function FocusableProvider(props: FocusableProviderProps): ReactElement;
function useFocusable(props?: FocusableOptions): FocusableAria;
function focusSafely(element: FocusableElement): void;
type Focusable = FocusableElement;These functions are re-exported for backward compatibility and convenience. For new code, consider importing them directly from their source packages.
interface FocusManagerOptions {
from?: Element;
tabbable?: boolean;
wrap?: boolean;
accept?: (node: Element) => boolean;
}
interface AriaFocusRingProps {
within?: boolean;
isTextInput?: boolean;
autoFocus?: boolean;
}
interface AriaHasTabbableChildOptions {
isDisabled?: boolean;
}
// Re-exported types from @react-aria/interactions
interface FocusableAria {
focusProps: DOMAttributes;
}
interface FocusableOptions {
isDisabled?: boolean;
onFocus?: (e: FocusEvent) => void;
onBlur?: (e: FocusEvent) => void;
onFocusChange?: (isFocused: boolean) => void;
}
interface FocusableProviderProps {
children: ReactNode;
}
// Re-exported from @react-types/shared and React
type FocusableElement = Element;
type RefObject<T> = { current: T | null };
type ReactNode = React.ReactNode;
type ReactElement = React.ReactElement;
type DOMAttributes = React.DOMAttributes<Element>;