Comprehensive library of unstyled React hooks providing accessible UI primitives with full WAI-ARIA compliance and internationalization support.
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Advanced focus management including focus rings, focus scopes, focus restoration, and keyboard navigation. These hooks and components provide comprehensive focus control for accessible applications.
Provides focus ring visualization with keyboard-only display and customizable styling.
/**
* Focus ring component that automatically shows/hides based on interaction method
* @param props - Focus ring configuration
* @returns Focus ring element
*/
function FocusRing(props: FocusRingProps): JSX.Element;
/**
* Provides focus ring behavior and state
* @param props - Focus ring configuration
* @returns Focus ring result with state and props
*/
function useFocusRing(props?: AriaFocusRingProps): FocusRingAria;
interface FocusRingProps {
/** Children render prop receiving focus ring state */
children: (states: { isFocusVisible: boolean; focusProps: DOMAttributes<Element> }) => ReactNode;
/** Whether focus ring is disabled */
isDisabled?: boolean;
/** Auto-focus behavior */
autoFocus?: boolean;
/** Focus ring class name when visible */
focusClass?: string;
/** Focus ring styles when visible */
focusStyle?: React.CSSProperties;
}
interface AriaFocusRingProps {
/** Whether focus ring is disabled */
isDisabled?: boolean;
/** Auto-focus behavior */
autoFocus?: boolean;
/** Within focus scope */
within?: boolean;
}
interface FocusRingAria {
/** Whether focus should be visible */
isFocusVisible: boolean;
/** Props to spread on the target element */
focusProps: DOMAttributes<Element>;
}Provides focus containment and restoration for modal dialogs and other containers.
/**
* Focus scope component that contains focus within its children
* @param props - Focus scope configuration
* @returns Focus scope container
*/
function FocusScope(props: FocusScopeProps): JSX.Element;
interface FocusScopeProps {
/** Children to contain focus within */
children: ReactNode;
/** Whether focus containment is active */
contain?: boolean;
/** Whether to restore focus when scope unmounts */
restoreFocus?: boolean;
/** Whether to auto-focus first element */
autoFocus?: boolean;
/** Element type to render as container */
elementType?: React.ElementType;
/** Whether focus should be contained */
isDisabled?: boolean;
}Provides programmatic focus management within a focus scope.
/**
* Provides focus management within a focus scope
* @returns Focus manager with navigation methods
*/
function useFocusManager(): FocusManager;
interface FocusManager {
/** Move focus to the next focusable element */
focusNext(opts?: FocusManagerOptions): HTMLElement | null;
/** Move focus to the previous focusable element */
focusPrevious(opts?: FocusManagerOptions): HTMLElement | null;
/** Move focus to the first focusable element */
focusFirst(opts?: FocusManagerOptions): HTMLElement | null;
/** Move focus to the last focusable element */
focusLast(opts?: FocusManagerOptions): HTMLElement | null;
}
interface FocusManagerOptions {
/** Whether to wrap focus at boundaries */
wrap?: boolean;
/** Tabbable elements only */
tabbable?: boolean;
/** From element to start search */
from?: Element;
/** Accept function to filter elements */
accept?: (element: Element) => boolean;
}Provides focusable element behavior with proper tab order management.
/**
* Provides focusable element behavior
* @param props - Focusable configuration
* @param ref - Ref to the focusable element
* @returns Focusable result with props and state
*/
function useFocusable(props: FocusableOptions, ref: RefObject<Element>): FocusableAria;
interface FocusableOptions {
/** Whether element should be excluded from tab order */
excludeFromTabOrder?: boolean;
/** Whether element is disabled */
isDisabled?: boolean;
/** Auto-focus behavior */
autoFocus?: boolean;
}
interface FocusableAria {
/** Props to spread on the focusable element */
focusableProps: DOMAttributes<Element>;
}Usage Examples:
import { useFocusable } from "react-aria";
// Basic focusable element
function CustomButton(props) {
const ref = useRef();
const { focusableProps } = useFocusable(props, ref);
return (
<button {...focusableProps} ref={ref}>
{props.children}
</button>
);
}
// Focusable with auto-focus
function AutoFocusButton(props) {
const ref = useRef();
const { focusableProps } = useFocusable({
autoFocus: true,
isDisabled: props.isDisabled
}, ref);
return (
<button {...focusableProps} ref={ref}>
{props.children}
</button>
);
}
// Focusable excluded from tab order
function SkipTabButton(props) {
const ref = useRef();
const { focusableProps } = useFocusable({
excludeFromTabOrder: true
}, ref);
return (
<button {...focusableProps} ref={ref}>
{props.children}
</button>
);
}Additional focus-related utilities for managing focus behavior.
/**
* Get all focusable elements within a container
* @param element - Container element to search within
* @param opts - Options for filtering focusable elements
* @returns Array of focusable elements
*/
function getFocusableElements(element: Element, opts?: {
/** Include only tabbable elements */
tabbable?: boolean;
/** Accept function to filter elements */
accept?: (element: Element) => boolean;
}): HTMLElement[];
/**
* Check if an element is focusable
* @param element - Element to check
* @param opts - Options for focusability check
* @returns Whether element is focusable
*/
function isFocusable(element: Element, opts?: {
/** Check if tabbable instead of just focusable */
tabbable?: boolean;
}): boolean;
/**
* Focus an element with appropriate timing
* @param element - Element to focus
* @param preventScroll - Whether to prevent scrolling to element
*/
function focusElement(element: HTMLElement | null, preventScroll?: boolean): void;
/**
* Restore focus to a previously focused element
* @param element - Element to restore focus to
* @param opts - Options for focus restoration
*/
function restoreFocus(element: HTMLElement | null, opts?: {
/** Whether to prevent scrolling */
preventScroll?: boolean;
}): void;Provides focus-visible detection for styling keyboard-focused elements.
/**
* Get the current focus-visible state globally
* @returns Whether focus should be visible
*/
function isFocusVisible(): boolean;
/**
* Set up global focus-visible detection
* This is called automatically by React Aria components
*/
function setupFocusVisible(): void;
/**
* Determine if focus should be visible for an element
* @param element - Element to check
* @param modality - Current input modality
* @returns Whether focus should be visible
*/
function shouldShowFocusRing(element: Element, modality?: string): boolean;Advanced focus event handling utilities.
/**
* Create a focus event handler that respects focus visible state
* @param onFocus - Handler to call when focus should be visible
* @param onBlur - Handler to call when focus is lost
* @returns Combined focus event handlers
*/
function createFocusHandler(
onFocus?: (e: FocusEvent) => void,
onBlur?: (e: FocusEvent) => void
): {
onFocus: (e: FocusEvent) => void;
onBlur: (e: FocusEvent) => void;
};
/**
* Wrap focus events to handle focus-visible state
* @param target - Target element
* @param onFocusVisible - Handler for focus visible changes
* @returns Cleanup function
*/
function trackFocusVisible(
target: Element,
onFocusVisible: (isFocusVisible: boolean) => void
): () => void;Usage Examples:
import { FocusRing, FocusScope, useFocusManager } from "react-aria";
// Focus ring with custom styling
function StyledButton(props) {
return (
<FocusRing focusClass="focus-visible">
{({ isFocusVisible, focusProps }) => (
<button
{...focusProps}
className={`btn ${isFocusVisible ? 'focus-visible' : ''}`}
>
{props.children}
</button>
)}
</FocusRing>
);
}
// Modal dialog with focus containment
function Modal({ isOpen, onClose, children }) {
if (!isOpen) return null;
return (
<div className="modal-backdrop">
<FocusScope contain restoreFocus autoFocus>
<div className="modal">
<button onClick={onClose}>×</button>
{children}
</div>
</FocusScope>
</div>
);
}
// Custom navigation with focus manager
function CustomToolbar() {
const focusManager = useFocusManager();
const handleKeyDown = (e) => {
switch (e.key) {
case 'ArrowRight':
focusManager.focusNext({ wrap: true });
break;
case 'ArrowLeft':
focusManager.focusPrevious({ wrap: true });
break;
case 'Home':
focusManager.focusFirst();
break;
case 'End':
focusManager.focusLast();
break;
}
};
return (
<div role="toolbar" onKeyDown={handleKeyDown}>
<button>Cut</button>
<button>Copy</button>
<button>Paste</button>
</div>
);
}For complex widgets like grids and trees, React Aria supports virtual focus patterns.
/**
* Implement virtual focus for grid-like components
* @param props - Virtual focus configuration
* @returns Virtual focus state and handlers
*/
function useVirtualFocus<T>(props: VirtualFocusProps<T>): VirtualFocusResult<T>;
interface VirtualFocusProps<T> {
/** Current collection */
collection: Collection<Node<T>>;
/** Currently focused key */
focusedKey?: Key;
/** Default focused key */
defaultFocusedKey?: Key;
/** Handler for focus changes */
onFocusChange?: (key: Key) => void;
/** Whether virtual focus is disabled */
isDisabled?: boolean;
}
interface VirtualFocusResult<T> {
/** Currently focused key */
focusedKey: Key | null;
/** Set the focused key */
setFocusedKey(key: Key): void;
/** Focus the next item */
focusNext(): void;
/** Focus the previous item */
focusPrevious(): void;
/** Focus the first item */
focusFirst(): void;
/** Focus the last item */
focusLast(): void;
}Advanced focus restoration patterns for complex interactions.
/**
* Track and restore focus across component lifecycles
* @param props - Focus restoration configuration
* @returns Focus restoration handlers
*/
function useFocusRestoration(props: FocusRestorationProps): FocusRestorationResult;
interface FocusRestorationProps {
/** Whether focus restoration is enabled */
isEnabled?: boolean;
/** Element to restore focus to */
restoreTarget?: HTMLElement | null;
/** Whether to restore focus on unmount */
restoreOnUnmount?: boolean;
}
interface FocusRestorationResult {
/** Save the current focus */
saveFocus(): void;
/** Restore the saved focus */
restoreFocus(): void;
/** Clear the saved focus */
clearSavedFocus(): void;
}type FocusStrategy = 'first' | 'last' | 'restore';
interface FocusableElement extends HTMLElement {
/** Whether element supports focus */
focus(options?: FocusOptions): void;
/** Tab index of the element */
tabIndex: number;
}
interface FocusOptions {
/** Whether to prevent scrolling to the element */
preventScroll?: boolean;
}
interface FocusEvent {
/** Type of focus event */
type: 'focus' | 'blur' | 'focusin' | 'focusout';
/** Target element */
target: Element;
/** Related target (element losing/gaining focus) */
relatedTarget: Element | null;
/** Whether event bubbles */
bubbles: boolean;
/** Whether event is cancelable */
cancelable: boolean;
}
interface FocusState {
/** Whether element has focus */
isFocused: boolean;
/** Whether focus should be visible */
isFocusVisible: boolean;
/** Whether element is within a focused container */
isFocusWithin: boolean;
}Install with Tessl CLI
npx tessl i tessl/npm-react-aria