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