npm-react-aria

Description
Comprehensive library of unstyled React hooks providing accessible UI primitives with full WAI-ARIA compliance and internationalization support.
Author
tessl
Last updated

How to use

npx @tessl/cli registry install tessl/npm-react-aria@3.43.0

focus-management.md docs/

1
# Focus Management
2
3
Advanced focus management including focus rings, focus scopes, focus restoration, and keyboard navigation. These hooks and components provide comprehensive focus control for accessible applications.
4
5
## Capabilities
6
7
### Focus Ring
8
9
Provides focus ring visualization with keyboard-only display and customizable styling.
10
11
```typescript { .api }
12
/**
13
* Focus ring component that automatically shows/hides based on interaction method
14
* @param props - Focus ring configuration
15
* @returns Focus ring element
16
*/
17
function FocusRing(props: FocusRingProps): JSX.Element;
18
19
/**
20
* Provides focus ring behavior and state
21
* @param props - Focus ring configuration
22
* @returns Focus ring result with state and props
23
*/
24
function useFocusRing(props?: AriaFocusRingProps): FocusRingAria;
25
26
interface FocusRingProps {
27
/** Children render prop receiving focus ring state */
28
children: (states: { isFocusVisible: boolean; focusProps: DOMAttributes<Element> }) => ReactNode;
29
/** Whether focus ring is disabled */
30
isDisabled?: boolean;
31
/** Auto-focus behavior */
32
autoFocus?: boolean;
33
/** Focus ring class name when visible */
34
focusClass?: string;
35
/** Focus ring styles when visible */
36
focusStyle?: React.CSSProperties;
37
}
38
39
interface AriaFocusRingProps {
40
/** Whether focus ring is disabled */
41
isDisabled?: boolean;
42
/** Auto-focus behavior */
43
autoFocus?: boolean;
44
/** Within focus scope */
45
within?: boolean;
46
}
47
48
interface FocusRingAria {
49
/** Whether focus should be visible */
50
isFocusVisible: boolean;
51
/** Props to spread on the target element */
52
focusProps: DOMAttributes<Element>;
53
}
54
```
55
56
### Focus Scope
57
58
Provides focus containment and restoration for modal dialogs and other containers.
59
60
```typescript { .api }
61
/**
62
* Focus scope component that contains focus within its children
63
* @param props - Focus scope configuration
64
* @returns Focus scope container
65
*/
66
function FocusScope(props: FocusScopeProps): JSX.Element;
67
68
interface FocusScopeProps {
69
/** Children to contain focus within */
70
children: ReactNode;
71
/** Whether focus containment is active */
72
contain?: boolean;
73
/** Whether to restore focus when scope unmounts */
74
restoreFocus?: boolean;
75
/** Whether to auto-focus first element */
76
autoFocus?: boolean;
77
/** Element type to render as container */
78
elementType?: React.ElementType;
79
/** Whether focus should be contained */
80
isDisabled?: boolean;
81
}
82
```
83
84
### Focus Manager
85
86
Provides programmatic focus management within a focus scope.
87
88
```typescript { .api }
89
/**
90
* Provides focus management within a focus scope
91
* @returns Focus manager with navigation methods
92
*/
93
function useFocusManager(): FocusManager;
94
95
interface FocusManager {
96
/** Move focus to the next focusable element */
97
focusNext(opts?: FocusManagerOptions): HTMLElement | null;
98
/** Move focus to the previous focusable element */
99
focusPrevious(opts?: FocusManagerOptions): HTMLElement | null;
100
/** Move focus to the first focusable element */
101
focusFirst(opts?: FocusManagerOptions): HTMLElement | null;
102
/** Move focus to the last focusable element */
103
focusLast(opts?: FocusManagerOptions): HTMLElement | null;
104
}
105
106
interface FocusManagerOptions {
107
/** Whether to wrap focus at boundaries */
108
wrap?: boolean;
109
/** Tabbable elements only */
110
tabbable?: boolean;
111
/** From element to start search */
112
from?: Element;
113
/** Accept function to filter elements */
114
accept?: (element: Element) => boolean;
115
}
116
```
117
118
### Focusable
119
120
Provides focusable element behavior with proper tab order management.
121
122
```typescript { .api }
123
/**
124
* Provides focusable element behavior
125
* @param props - Focusable configuration
126
* @param ref - Ref to the focusable element
127
* @returns Focusable result with props and state
128
*/
129
function useFocusable(props: FocusableOptions, ref: RefObject<Element>): FocusableAria;
130
131
interface FocusableOptions {
132
/** Whether element should be excluded from tab order */
133
excludeFromTabOrder?: boolean;
134
/** Whether element is disabled */
135
isDisabled?: boolean;
136
/** Auto-focus behavior */
137
autoFocus?: boolean;
138
}
139
140
interface FocusableAria {
141
/** Props to spread on the focusable element */
142
focusableProps: DOMAttributes<Element>;
143
}
144
```
145
146
**Usage Examples:**
147
148
```typescript
149
import { useFocusable } from "react-aria";
150
151
// Basic focusable element
152
function CustomButton(props) {
153
const ref = useRef();
154
const { focusableProps } = useFocusable(props, ref);
155
156
return (
157
<button {...focusableProps} ref={ref}>
158
{props.children}
159
</button>
160
);
161
}
162
163
// Focusable with auto-focus
164
function AutoFocusButton(props) {
165
const ref = useRef();
166
const { focusableProps } = useFocusable({
167
autoFocus: true,
168
isDisabled: props.isDisabled
169
}, ref);
170
171
return (
172
<button {...focusableProps} ref={ref}>
173
{props.children}
174
</button>
175
);
176
}
177
178
// Focusable excluded from tab order
179
function SkipTabButton(props) {
180
const ref = useRef();
181
const { focusableProps } = useFocusable({
182
excludeFromTabOrder: true
183
}, ref);
184
185
return (
186
<button {...focusableProps} ref={ref}>
187
{props.children}
188
</button>
189
);
190
}
191
```
192
193
### Focus Utilities
194
195
Additional focus-related utilities for managing focus behavior.
196
197
```typescript { .api }
198
/**
199
* Get all focusable elements within a container
200
* @param element - Container element to search within
201
* @param opts - Options for filtering focusable elements
202
* @returns Array of focusable elements
203
*/
204
function getFocusableElements(element: Element, opts?: {
205
/** Include only tabbable elements */
206
tabbable?: boolean;
207
/** Accept function to filter elements */
208
accept?: (element: Element) => boolean;
209
}): HTMLElement[];
210
211
/**
212
* Check if an element is focusable
213
* @param element - Element to check
214
* @param opts - Options for focusability check
215
* @returns Whether element is focusable
216
*/
217
function isFocusable(element: Element, opts?: {
218
/** Check if tabbable instead of just focusable */
219
tabbable?: boolean;
220
}): boolean;
221
222
/**
223
* Focus an element with appropriate timing
224
* @param element - Element to focus
225
* @param preventScroll - Whether to prevent scrolling to element
226
*/
227
function focusElement(element: HTMLElement | null, preventScroll?: boolean): void;
228
229
/**
230
* Restore focus to a previously focused element
231
* @param element - Element to restore focus to
232
* @param opts - Options for focus restoration
233
*/
234
function restoreFocus(element: HTMLElement | null, opts?: {
235
/** Whether to prevent scrolling */
236
preventScroll?: boolean;
237
}): void;
238
```
239
240
### Focus Visible Detection
241
242
Provides focus-visible detection for styling keyboard-focused elements.
243
244
```typescript { .api }
245
/**
246
* Get the current focus-visible state globally
247
* @returns Whether focus should be visible
248
*/
249
function isFocusVisible(): boolean;
250
251
/**
252
* Set up global focus-visible detection
253
* This is called automatically by React Aria components
254
*/
255
function setupFocusVisible(): void;
256
257
/**
258
* Determine if focus should be visible for an element
259
* @param element - Element to check
260
* @param modality - Current input modality
261
* @returns Whether focus should be visible
262
*/
263
function shouldShowFocusRing(element: Element, modality?: string): boolean;
264
```
265
266
### Focus Event Handling
267
268
Advanced focus event handling utilities.
269
270
```typescript { .api }
271
/**
272
* Create a focus event handler that respects focus visible state
273
* @param onFocus - Handler to call when focus should be visible
274
* @param onBlur - Handler to call when focus is lost
275
* @returns Combined focus event handlers
276
*/
277
function createFocusHandler(
278
onFocus?: (e: FocusEvent) => void,
279
onBlur?: (e: FocusEvent) => void
280
): {
281
onFocus: (e: FocusEvent) => void;
282
onBlur: (e: FocusEvent) => void;
283
};
284
285
/**
286
* Wrap focus events to handle focus-visible state
287
* @param target - Target element
288
* @param onFocusVisible - Handler for focus visible changes
289
* @returns Cleanup function
290
*/
291
function trackFocusVisible(
292
target: Element,
293
onFocusVisible: (isFocusVisible: boolean) => void
294
): () => void;
295
```
296
297
**Usage Examples:**
298
299
```typescript
300
import { FocusRing, FocusScope, useFocusManager } from "react-aria";
301
302
// Focus ring with custom styling
303
function StyledButton(props) {
304
return (
305
<FocusRing focusClass="focus-visible">
306
{({ isFocusVisible, focusProps }) => (
307
<button
308
{...focusProps}
309
className={`btn ${isFocusVisible ? 'focus-visible' : ''}`}
310
>
311
{props.children}
312
</button>
313
)}
314
</FocusRing>
315
);
316
}
317
318
// Modal dialog with focus containment
319
function Modal({ isOpen, onClose, children }) {
320
if (!isOpen) return null;
321
322
return (
323
<div className="modal-backdrop">
324
<FocusScope contain restoreFocus autoFocus>
325
<div className="modal">
326
<button onClick={onClose}>×</button>
327
{children}
328
</div>
329
</FocusScope>
330
</div>
331
);
332
}
333
334
// Custom navigation with focus manager
335
function CustomToolbar() {
336
const focusManager = useFocusManager();
337
338
const handleKeyDown = (e) => {
339
switch (e.key) {
340
case 'ArrowRight':
341
focusManager.focusNext({ wrap: true });
342
break;
343
case 'ArrowLeft':
344
focusManager.focusPrevious({ wrap: true });
345
break;
346
case 'Home':
347
focusManager.focusFirst();
348
break;
349
case 'End':
350
focusManager.focusLast();
351
break;
352
}
353
};
354
355
return (
356
<div role="toolbar" onKeyDown={handleKeyDown}>
357
<button>Cut</button>
358
<button>Copy</button>
359
<button>Paste</button>
360
</div>
361
);
362
}
363
```
364
365
## Advanced Focus Patterns
366
367
### Virtual Focus
368
369
For complex widgets like grids and trees, React Aria supports virtual focus patterns.
370
371
```typescript { .api }
372
/**
373
* Implement virtual focus for grid-like components
374
* @param props - Virtual focus configuration
375
* @returns Virtual focus state and handlers
376
*/
377
function useVirtualFocus<T>(props: VirtualFocusProps<T>): VirtualFocusResult<T>;
378
379
interface VirtualFocusProps<T> {
380
/** Current collection */
381
collection: Collection<Node<T>>;
382
/** Currently focused key */
383
focusedKey?: Key;
384
/** Default focused key */
385
defaultFocusedKey?: Key;
386
/** Handler for focus changes */
387
onFocusChange?: (key: Key) => void;
388
/** Whether virtual focus is disabled */
389
isDisabled?: boolean;
390
}
391
392
interface VirtualFocusResult<T> {
393
/** Currently focused key */
394
focusedKey: Key | null;
395
/** Set the focused key */
396
setFocusedKey(key: Key): void;
397
/** Focus the next item */
398
focusNext(): void;
399
/** Focus the previous item */
400
focusPrevious(): void;
401
/** Focus the first item */
402
focusFirst(): void;
403
/** Focus the last item */
404
focusLast(): void;
405
}
406
```
407
408
### Focus Restoration
409
410
Advanced focus restoration patterns for complex interactions.
411
412
```typescript { .api }
413
/**
414
* Track and restore focus across component lifecycles
415
* @param props - Focus restoration configuration
416
* @returns Focus restoration handlers
417
*/
418
function useFocusRestoration(props: FocusRestorationProps): FocusRestorationResult;
419
420
interface FocusRestorationProps {
421
/** Whether focus restoration is enabled */
422
isEnabled?: boolean;
423
/** Element to restore focus to */
424
restoreTarget?: HTMLElement | null;
425
/** Whether to restore focus on unmount */
426
restoreOnUnmount?: boolean;
427
}
428
429
interface FocusRestorationResult {
430
/** Save the current focus */
431
saveFocus(): void;
432
/** Restore the saved focus */
433
restoreFocus(): void;
434
/** Clear the saved focus */
435
clearSavedFocus(): void;
436
}
437
```
438
439
## Types
440
441
```typescript { .api }
442
type FocusStrategy = 'first' | 'last' | 'restore';
443
444
interface FocusableElement extends HTMLElement {
445
/** Whether element supports focus */
446
focus(options?: FocusOptions): void;
447
/** Tab index of the element */
448
tabIndex: number;
449
}
450
451
interface FocusOptions {
452
/** Whether to prevent scrolling to the element */
453
preventScroll?: boolean;
454
}
455
456
interface FocusEvent {
457
/** Type of focus event */
458
type: 'focus' | 'blur' | 'focusin' | 'focusout';
459
/** Target element */
460
target: Element;
461
/** Related target (element losing/gaining focus) */
462
relatedTarget: Element | null;
463
/** Whether event bubbles */
464
bubbles: boolean;
465
/** Whether event is cancelable */
466
cancelable: boolean;
467
}
468
469
interface FocusState {
470
/** Whether element has focus */
471
isFocused: boolean;
472
/** Whether focus should be visible */
473
isFocusVisible: boolean;
474
/** Whether element is within a focused container */
475
isFocusWithin: boolean;
476
}
477
```