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

overlays-modals.md docs/

1
# Overlays and Modals
2
3
Overlay components including dialogs, popovers, tooltips, and modals with proper focus management, positioning, and accessibility. All overlays handle escape key, click outside, and focus restoration.
4
5
## Capabilities
6
7
### Dialog
8
9
Provides modal dialog behavior with focus containment and accessibility.
10
11
```typescript { .api }
12
/**
13
* Provides dialog behavior and accessibility
14
* @param props - Dialog configuration
15
* @param ref - Ref to the dialog element
16
* @returns Dialog props
17
*/
18
function useDialog(props: AriaDialogProps, ref: RefObject<Element>): DialogAria;
19
20
interface AriaDialogProps {
21
/** Role of the dialog */
22
role?: 'dialog' | 'alertdialog';
23
/** ID of the dialog */
24
id?: string;
25
/** Accessible name for the dialog */
26
'aria-label'?: string;
27
/** ID of element that labels the dialog */
28
'aria-labelledby'?: string;
29
/** ID of element that describes the dialog */
30
'aria-describedby'?: string;
31
}
32
33
interface DialogAria {
34
/** Props for the dialog element */
35
dialogProps: DOMAttributes<Element>;
36
/** Props for the dialog title element */
37
titleProps: DOMAttributes<Element>;
38
}
39
```
40
41
### Disclosure
42
43
Provides disclosure behavior for expandable/collapsible content sections.
44
45
```typescript { .api }
46
/**
47
* Provides disclosure behavior and accessibility
48
* @param props - Disclosure configuration
49
* @param ref - Ref to the disclosure element
50
* @returns Disclosure props and state
51
*/
52
function useDisclosure(props: AriaDisclosureProps, ref: RefObject<Element>): DisclosureAria;
53
54
interface AriaDisclosureProps {
55
/** Whether the disclosure is expanded */
56
isExpanded?: boolean;
57
/** Default expanded state (uncontrolled) */
58
defaultExpanded?: boolean;
59
/** Handler called when expansion changes */
60
onExpandedChange?: (isExpanded: boolean) => void;
61
/** Whether the disclosure is disabled */
62
isDisabled?: boolean;
63
}
64
65
interface DisclosureAria {
66
/** Props for the disclosure button */
67
buttonProps: ButtonHTMLAttributes<HTMLButtonElement>;
68
/** Props for the disclosure panel */
69
panelProps: DOMAttributes<Element>;
70
/** Whether the disclosure is expanded */
71
isExpanded: boolean;
72
}
73
```
74
75
### Modal
76
77
Provides modal overlay behavior with backdrop and focus management.
78
79
```typescript { .api }
80
/**
81
* Provides modal behavior and accessibility
82
* @param options - Modal configuration options
83
* @returns Modal props and state
84
*/
85
function useModal(options?: AriaModalOptions): ModalAria;
86
87
/**
88
* Provides modal overlay behavior
89
* @param props - Modal overlay configuration
90
* @param state - Modal state
91
* @param ref - Ref to the overlay element
92
* @returns Modal overlay props
93
*/
94
function useModalOverlay(props: AriaModalOverlayProps, state: OverlayTriggerState, ref: RefObject<Element>): ModalOverlayAria;
95
96
/**
97
* Provides modal provider context
98
* @param props - Modal provider configuration
99
* @returns Modal provider props and state
100
*/
101
function useModalProvider(props: ModalProviderProps): ModalProviderAria;
102
103
interface AriaModalOptions {
104
/** Whether the modal is open */
105
isOpen?: boolean;
106
/** Handler called when the modal should close */
107
onClose?: () => void;
108
/** Whether the modal is keyboard modal */
109
isKeyboardDismissDisabled?: boolean;
110
/** Whether to disable outside clicks */
111
isDismissable?: boolean;
112
}
113
114
interface ModalAria {
115
/** Props for the modal element */
116
modalProps: DOMAttributes<Element>;
117
/** Props for the underlay element */
118
underlayProps: DOMAttributes<Element>;
119
}
120
121
interface AriaModalOverlayProps {
122
/** Whether the overlay is open */
123
isOpen?: boolean;
124
/** Handler called when the overlay should close */
125
onClose?: () => void;
126
/** Whether the overlay is dismissable */
127
isDismissable?: boolean;
128
/** Whether keyboard dismissal is disabled */
129
isKeyboardDismissDisabled?: boolean;
130
/** Whether to prevent scrolling */
131
shouldCloseOnBlur?: boolean;
132
}
133
134
interface ModalOverlayAria {
135
/** Props for the modal overlay element */
136
modalProps: DOMAttributes<Element>;
137
/** Props for the underlay element */
138
underlayProps: DOMAttributes<Element>;
139
}
140
```
141
142
### Popover
143
144
Provides popover behavior with positioning and trigger management.
145
146
```typescript { .api }
147
/**
148
* Provides popover behavior and accessibility
149
* @param props - Popover configuration
150
* @param state - Popover state
151
* @param ref - Ref to the popover element
152
* @returns Popover props
153
*/
154
function usePopover(props: AriaPopoverProps, state: PopoverState, ref: RefObject<Element>): PopoverAria;
155
156
interface AriaPopoverProps {
157
/** Type of popover */
158
triggerRef: RefObject<Element>;
159
/** Whether the popover is non-modal */
160
isNonModal?: boolean;
161
/** Trigger source for the popover */
162
triggerSource?: string;
163
/** Whether keyboard dismissal is disabled */
164
isKeyboardDismissDisabled?: boolean;
165
/** Whether the popover should close on blur */
166
shouldCloseOnBlur?: boolean;
167
/** Whether to flip placement when space is limited */
168
shouldFlip?: boolean;
169
/** Boundary element for flipping */
170
boundaryElement?: Element;
171
/** Scroll ref for repositioning */
172
scrollRef?: RefObject<Element>;
173
/** Whether the popover should update position */
174
shouldUpdatePosition?: boolean;
175
/** Arrow boundary offset */
176
arrowBoundaryOffset?: number;
177
/** Placement of the popover */
178
placement?: Placement;
179
/** Container padding */
180
containerPadding?: number;
181
/** Offset from trigger */
182
offset?: number;
183
/** Cross offset */
184
crossOffset?: number;
185
/** Whether the popover should close on interact outside */
186
shouldCloseOnInteractOutside?: (element: Element) => boolean;
187
/** Max height of the popover */
188
maxHeight?: number;
189
/** Arrow size */
190
arrowSize?: number;
191
/** Arrow boundary offset */
192
arrowBoundaryOffset?: number;
193
}
194
195
interface PopoverAria {
196
/** Props for the popover element */
197
popoverProps: DOMAttributes<Element>;
198
/** Props for the arrow element */
199
arrowProps: DOMAttributes<Element>;
200
/** Placement that was actually used */
201
placement: PlacementAxis;
202
/** Arrow props */
203
arrowProps: DOMAttributes<Element>;
204
/** Props for the underlay element */
205
underlayProps: DOMAttributes<Element>;
206
}
207
```
208
209
### Overlay
210
211
Provides base overlay behavior and positioning.
212
213
```typescript { .api }
214
/**
215
* Provides overlay behavior and accessibility
216
* @param props - Overlay configuration
217
* @param ref - Ref to the overlay element
218
* @returns Overlay props
219
*/
220
function useOverlay(props: AriaOverlayProps, ref: RefObject<Element>): OverlayAria;
221
222
/**
223
* Provides overlay positioning behavior
224
* @param props - Position configuration
225
* @param ref - Ref to the overlay element
226
* @returns Position props and placement
227
*/
228
function useOverlayPosition(props: AriaPositionProps, ref: RefObject<Element>): PositionAria;
229
230
/**
231
* Provides overlay trigger behavior
232
* @param props - Overlay trigger configuration
233
* @param state - Overlay trigger state
234
* @param ref - Ref to the trigger element
235
* @returns Overlay trigger props
236
*/
237
function useOverlayTrigger(props: OverlayTriggerProps, state: OverlayTriggerState, ref?: RefObject<Element>): OverlayTriggerAria;
238
239
interface AriaOverlayProps {
240
/** Whether the overlay is open */
241
isOpen?: boolean;
242
/** Handler called when the overlay should close */
243
onClose?: () => void;
244
/** Whether the overlay should close on blur */
245
shouldCloseOnBlur?: boolean;
246
/** Whether the overlay is dismissable */
247
isDismissable?: boolean;
248
/** Whether keyboard dismissal is disabled */
249
isKeyboardDismissDisabled?: boolean;
250
/** Whether to prevent scrolling */
251
shouldCloseOnInteractOutside?: (element: Element) => boolean;
252
}
253
254
interface OverlayAria {
255
/** Props for the overlay element */
256
overlayProps: DOMAttributes<Element>;
257
/** Props for the underlay element */
258
underlayProps: DOMAttributes<Element>;
259
}
260
261
interface AriaPositionProps extends PositionProps {
262
/** Element to position relative to */
263
targetRef: RefObject<Element>;
264
/** Element to position */
265
overlayRef: RefObject<Element>;
266
/** Scroll refs for repositioning */
267
scrollRef?: RefObject<Element>;
268
/** Placement preference */
269
placement?: Placement;
270
/** Container padding */
271
containerPadding?: number;
272
/** Offset from target */
273
offset?: number;
274
/** Cross-axis offset */
275
crossOffset?: number;
276
/** Whether to flip when space is limited */
277
shouldFlip?: boolean;
278
/** Boundary element */
279
boundaryElement?: Element;
280
/** Whether position should update */
281
shouldUpdatePosition?: boolean;
282
/** Whether the overlay is open */
283
isOpen?: boolean;
284
/** Handler called when the overlay should close */
285
onClose?: () => void;
286
/** Max height */
287
maxHeight?: number;
288
/** Arrow size for popover arrows */
289
arrowSize?: number;
290
/** Arrow boundary offset */
291
arrowBoundaryOffset?: number;
292
}
293
294
interface PositionAria {
295
/** Props for the overlay element */
296
overlayProps: DOMAttributes<Element>;
297
/** Props for the arrow element */
298
arrowProps: DOMAttributes<Element>;
299
/** Placement that was used */
300
placement: PlacementAxis;
301
/** Update position manually */
302
updatePosition(): void;
303
}
304
305
interface OverlayTriggerProps {
306
/** Type of overlay */
307
type: 'dialog' | 'menu' | 'listbox' | 'tree' | 'grid';
308
/** Whether the overlay is open */
309
isOpen?: boolean;
310
/** Default open state (uncontrolled) */
311
defaultOpen?: boolean;
312
/** Handler called when open state changes */
313
onOpenChange?: (isOpen: boolean) => void;
314
}
315
316
interface OverlayTriggerAria {
317
/** Props for the trigger element */
318
triggerProps: ButtonHTMLAttributes<HTMLButtonElement>;
319
/** Props for the overlay element */
320
overlayProps: DOMAttributes<Element>;
321
}
322
```
323
324
### Tooltip
325
326
Provides tooltip behavior with hover and focus triggers.
327
328
```typescript { .api }
329
/**
330
* Provides tooltip behavior and accessibility
331
* @param props - Tooltip configuration
332
* @param state - Tooltip trigger state
333
* @returns Tooltip props
334
*/
335
function useTooltip(props: AriaTooltipProps, state: TooltipTriggerState): TooltipAria;
336
337
/**
338
* Provides tooltip trigger behavior
339
* @param props - Tooltip trigger configuration
340
* @param state - Tooltip trigger state
341
* @param ref - Ref to the trigger element
342
* @returns Tooltip trigger props
343
*/
344
function useTooltipTrigger(props: TooltipTriggerProps, state: TooltipTriggerState, ref?: RefObject<Element>): TooltipTriggerAria;
345
346
interface AriaTooltipProps {
347
/** Whether the tooltip is open */
348
isOpen?: boolean;
349
/** ID for the tooltip */
350
id?: string;
351
}
352
353
interface TooltipAria {
354
/** Props for the tooltip element */
355
tooltipProps: DOMAttributes<Element>;
356
}
357
358
interface TooltipTriggerProps {
359
/** Whether the tooltip is disabled */
360
isDisabled?: boolean;
361
/** Delay before showing tooltip */
362
delay?: number;
363
/** Close delay */
364
closeDelay?: number;
365
/** Trigger events */
366
trigger?: 'focus' | 'focus+hover';
367
/** Whether the tooltip is open */
368
isOpen?: boolean;
369
/** Default open state (uncontrolled) */
370
defaultOpen?: boolean;
371
/** Handler called when open state changes */
372
onOpenChange?: (isOpen: boolean) => void;
373
}
374
375
interface TooltipTriggerAria {
376
/** Props for the trigger element */
377
triggerProps: DOMAttributes<Element>;
378
/** Props for the tooltip element */
379
tooltipProps: DOMAttributes<Element>;
380
}
381
```
382
383
### Toast
384
385
Provides toast notification behavior with timeout and positioning.
386
387
```typescript { .api }
388
/**
389
* Provides toast behavior and accessibility
390
* @param props - Toast configuration
391
* @param state - Toast state
392
* @param ref - Ref to the toast element
393
* @returns Toast props
394
*/
395
function useToast(props: AriaToastProps, state: ToastState, ref: RefObject<Element>): ToastAria;
396
397
/**
398
* Provides toast region behavior for managing multiple toasts
399
* @param props - Toast region configuration
400
* @param state - Toast region state
401
* @param ref - Ref to the toast region element
402
* @returns Toast region props
403
*/
404
function useToastRegion(props: AriaToastRegionProps, state: ToastRegionState, ref: RefObject<Element>): ToastRegionAria;
405
406
interface AriaToastProps {
407
/** Toast priority level */
408
priority?: 'low' | 'normal' | 'high';
409
/** Whether the toast should auto-dismiss */
410
shouldCloseOnAction?: boolean;
411
/** Handler called when the toast is closed */
412
onClose?: () => void;
413
}
414
415
interface ToastAria {
416
/** Props for the toast element */
417
toastProps: DOMAttributes<Element>;
418
/** Props for the title element */
419
titleProps: DOMAttributes<Element>;
420
/** Props for the description element */
421
descriptionProps: DOMAttributes<Element>;
422
/** Props for the close button */
423
closeButtonProps: ButtonHTMLAttributes<HTMLButtonElement>;
424
}
425
426
interface AriaToastRegionProps {
427
/** Accessible label for the toast region */
428
'aria-label'?: string;
429
/** ID of element that labels the toast region */
430
'aria-labelledby'?: string;
431
}
432
433
interface ToastRegionAria {
434
/** Props for the toast region element */
435
regionProps: DOMAttributes<Element>;
436
}
437
```
438
439
### Prevent Scroll
440
441
Provides scroll prevention behavior for modal overlays.
442
443
```typescript { .api }
444
/**
445
* Provides scroll prevention behavior
446
* @param options - Scroll prevention options
447
* @returns Scroll prevention state
448
*/
449
function usePreventScroll(options?: { isDisabled?: boolean }): void;
450
```
451
452
### Overlay Components
453
454
```typescript { .api }
455
/**
456
* Button for dismissing overlays
457
*/
458
function DismissButton(props: DismissButtonProps): JSX.Element;
459
460
/**
461
* Provider for modal context
462
*/
463
function ModalProvider(props: { children: ReactNode }): JSX.Element;
464
465
/**
466
* Base overlay component
467
*/
468
function Overlay(props: OverlayProps): JSX.Element;
469
470
/**
471
* Container for overlay portals
472
*/
473
function OverlayContainer(props: OverlayContainerProps): JSX.Element;
474
475
/**
476
* Provider for overlay context
477
*/
478
function OverlayProvider(props: { children: ReactNode }): JSX.Element;
479
480
/**
481
* Portal provider (marked as unsafe)
482
*/
483
function UNSAFE_PortalProvider(props: { children: ReactNode; getContainer?: () => Element }): JSX.Element;
484
485
interface DismissButtonProps {
486
/** Handler called when button is pressed */
487
onDismiss?: () => void;
488
}
489
490
interface OverlayProps {
491
/** Children to render in overlay */
492
children: ReactNode;
493
/** Whether the overlay is open */
494
isOpen?: boolean;
495
/** Container to render overlay in */
496
container?: Element;
497
/** Handler called when overlay should close */
498
onClose?: () => void;
499
}
500
501
interface OverlayContainerProps {
502
/** Container element to render portals in */
503
portalContainer?: Element;
504
/** Children to render */
505
children: ReactNode;
506
}
507
```
508
509
## Types
510
511
```typescript { .api }
512
type Placement =
513
| 'bottom'
514
| 'bottom left'
515
| 'bottom right'
516
| 'bottom start'
517
| 'bottom end'
518
| 'top'
519
| 'top left'
520
| 'top right'
521
| 'top start'
522
| 'top end'
523
| 'left'
524
| 'left top'
525
| 'left bottom'
526
| 'start'
527
| 'start top'
528
| 'start bottom'
529
| 'right'
530
| 'right top'
531
| 'right bottom'
532
| 'end'
533
| 'end top'
534
| 'end bottom';
535
536
type PlacementAxis = 'top' | 'bottom' | 'left' | 'right' | 'center';
537
538
interface OverlayTriggerState {
539
/** Whether the overlay is open */
540
isOpen: boolean;
541
/** Set the open state */
542
setOpen(isOpen: boolean): void;
543
/** Open the overlay */
544
open(): void;
545
/** Close the overlay */
546
close(): void;
547
/** Toggle the overlay */
548
toggle(): void;
549
}
550
551
interface PopoverState extends OverlayTriggerState {
552
/** Trigger source */
553
triggerSource?: string;
554
/** Set trigger source */
555
setTriggerSource(source: string): void;
556
}
557
558
interface TooltipTriggerState extends OverlayTriggerState {
559
/** Whether the tooltip is immediately open */
560
isWarmupFinished: boolean;
561
/** Warm up the tooltip globally */
562
warmUp(): void;
563
/** Cool down the tooltip globally */
564
coolDown(): void;
565
}
566
567
interface ToastState {
568
/** Whether the toast is visible */
569
isVisible: boolean;
570
/** Whether the toast is paused */
571
isPaused: boolean;
572
/** Remaining time before auto-dismiss */
573
remainingTime: number;
574
/** Pause the toast */
575
pause(): void;
576
/** Resume the toast */
577
resume(): void;
578
/** Close the toast */
579
close(): void;
580
}
581
582
interface ToastRegionState {
583
/** List of toasts in the region */
584
toasts: Toast[];
585
/** Add a toast */
586
add(toast: Toast): void;
587
/** Remove a toast */
588
remove(key: string): void;
589
/** Pause all toasts */
590
pauseAll(): void;
591
/** Resume all toasts */
592
resumeAll(): void;
593
}
594
595
interface Toast {
596
/** Unique key for the toast */
597
key: string;
598
/** Toast content */
599
content: ReactNode;
600
/** Toast priority */
601
priority?: 'low' | 'normal' | 'high';
602
/** Auto-dismiss timeout */
603
timeout?: number;
604
/** Handler called when closed */
605
onClose?: () => void;
606
}
607
608
interface PositionProps {
609
/** Container padding */
610
containerPadding?: number;
611
/** Offset from target */
612
offset?: number;
613
/** Cross-axis offset */
614
crossOffset?: number;
615
/** Whether to flip placement */
616
shouldFlip?: boolean;
617
/** Boundary element */
618
boundaryElement?: Element;
619
/** Max height */
620
maxHeight?: number;
621
}
622
```