0
# React Modal
1
2
React Modal is an accessible modal dialog component for React.JS applications. It provides comprehensive ARIA accessibility support, keyboard navigation, focus management, and extensive customization options for creating modal dialogs that work seamlessly with screen readers and assistive technologies.
3
4
## Package Information
5
6
- **Package Name**: react-modal
7
- **Package Type**: npm
8
- **Language**: JavaScript/TypeScript
9
- **Installation**: `npm install react-modal`
10
11
## Core Imports
12
13
```javascript
14
import Modal from 'react-modal';
15
```
16
17
For CommonJS:
18
19
```javascript
20
const Modal = require('react-modal');
21
```
22
23
## Basic Usage
24
25
```javascript
26
import React, { useState } from 'react';
27
import Modal from 'react-modal';
28
29
// Set app element for accessibility (required)
30
Modal.setAppElement('#yourAppElement');
31
32
function App() {
33
const [modalIsOpen, setIsOpen] = useState(false);
34
35
function openModal() {
36
setIsOpen(true);
37
}
38
39
function closeModal() {
40
setIsOpen(false);
41
}
42
43
return (
44
<div>
45
<button onClick={openModal}>Open Modal</button>
46
<Modal
47
isOpen={modalIsOpen}
48
onRequestClose={closeModal}
49
contentLabel="Example Modal"
50
>
51
<h2>Hello Modal</h2>
52
<button onClick={closeModal}>Close</button>
53
</Modal>
54
</div>
55
);
56
}
57
```
58
59
## Architecture
60
61
React Modal uses a portal-based architecture that renders the modal outside the normal React component tree:
62
63
- **Portal Rendering**: Uses React portals to render modals at the document body level, avoiding z-index issues
64
- **Accessibility Layer**: Implements ARIA standards with focus management and screen reader support
65
- **Event Management**: Handles keyboard navigation, overlay clicks, and focus trapping
66
- **Style System**: Supports both inline styles and CSS classes with state-based class names
67
68
## Capabilities
69
70
### Modal Component
71
72
The main Modal component that renders an accessible dialog with overlay and content areas.
73
74
```javascript { .api }
75
/**
76
* Accessible modal dialog component
77
*/
78
function Modal(props: ModalProps): JSX.Element;
79
80
interface ModalProps {
81
/** Required: Controls modal visibility */
82
isOpen: boolean;
83
84
/** Styling props */
85
style?: {
86
content?: React.CSSProperties;
87
overlay?: React.CSSProperties;
88
};
89
className?: string | ClassNameConfig;
90
overlayClassName?: string | ClassNameConfig;
91
92
/** Portal and DOM props */
93
portalClassName?: string;
94
bodyOpenClassName?: string;
95
htmlOpenClassName?: string;
96
parentSelector?: () => HTMLElement;
97
98
/** Accessibility props */
99
appElement?: HTMLElement | HTMLElement[] | NodeList | string;
100
ariaHideApp?: boolean;
101
role?: string;
102
contentLabel?: string;
103
aria?: { [key: string]: string };
104
105
/** Behavior props */
106
shouldFocusAfterRender?: boolean;
107
shouldCloseOnOverlayClick?: boolean;
108
shouldCloseOnEsc?: boolean;
109
shouldReturnFocusAfterClose?: boolean;
110
preventScroll?: boolean;
111
closeTimeoutMS?: number;
112
113
/** Event handlers */
114
onAfterOpen?: (options: { overlayEl: Element; contentEl: Element }) => void;
115
onAfterClose?: () => void;
116
onRequestClose?: (event: React.MouseEvent | React.KeyboardEvent) => void;
117
118
/** Refs and custom elements */
119
overlayRef?: (instance: HTMLDivElement) => void;
120
contentRef?: (instance: HTMLDivElement) => void;
121
overlayElement?: (props: any, contentEl: React.ReactElement) => React.ReactElement;
122
contentElement?: (props: any, children: React.ReactNode) => React.ReactElement;
123
124
/** Additional attributes */
125
data?: { [key: string]: string };
126
id?: string;
127
testId?: string;
128
children?: React.ReactNode;
129
}
130
131
interface ClassNameConfig {
132
base: string;
133
afterOpen: string;
134
beforeClose: string;
135
}
136
```
137
138
### Static Methods
139
140
Configuration methods available on the Modal component.
141
142
```javascript { .api }
143
/**
144
* Sets the app element for accessibility. Must be called before using modals.
145
* @param element - DOM element, selector string, or array of elements to hide from screen readers
146
*/
147
Modal.setAppElement(element: HTMLElement | HTMLElement[] | NodeList | string): void;
148
149
/**
150
* Development-only: Sets custom HTML element creation function for testing (NODE_ENV !== "production")
151
* @param fn - Function to create HTML elements
152
*/
153
Modal.setCreateHTMLElement?(fn: (name: string) => HTMLElement): void;
154
```
155
156
### Static Properties
157
158
Pre-defined styling and constants available on the Modal component.
159
160
```javascript { .api }
161
/**
162
* Default styles for modal overlay and content
163
*/
164
Modal.defaultStyles: {
165
overlay: {
166
position: 'fixed';
167
top: 0;
168
left: 0;
169
right: 0;
170
bottom: 0;
171
backgroundColor: 'rgba(255, 255, 255, 0.75)';
172
};
173
content: {
174
position: 'absolute';
175
top: '40px';
176
left: '40px';
177
right: '40px';
178
bottom: '40px';
179
border: '1px solid #ccc';
180
background: '#fff';
181
overflow: 'auto';
182
WebkitOverflowScrolling: 'touch';
183
borderRadius: '4px';
184
outline: 'none';
185
padding: '20px';
186
};
187
};
188
```
189
190
191
## Styling
192
193
### Inline Styles
194
195
```javascript
196
const customStyles = {
197
content: {
198
top: '50%',
199
left: '50%',
200
right: 'auto',
201
bottom: 'auto',
202
marginRight: '-50%',
203
transform: 'translate(-50%, -50%)',
204
},
205
};
206
207
<Modal
208
isOpen={modalIsOpen}
209
style={customStyles}
210
contentLabel="Centered Modal"
211
>
212
<h2>Centered Content</h2>
213
</Modal>
214
```
215
216
### CSS Classes
217
218
```javascript
219
<Modal
220
isOpen={modalIsOpen}
221
className="modal-content"
222
overlayClassName="modal-overlay"
223
contentLabel="Styled Modal"
224
>
225
<h2>Custom Styled Modal</h2>
226
</Modal>
227
```
228
229
### State-based Classes
230
231
```javascript
232
<Modal
233
isOpen={modalIsOpen}
234
className={{
235
base: 'modal-content',
236
afterOpen: 'modal-content--after-open',
237
beforeClose: 'modal-content--before-close'
238
}}
239
overlayClassName={{
240
base: 'modal-overlay',
241
afterOpen: 'modal-overlay--after-open',
242
beforeClose: 'modal-overlay--before-close'
243
}}
244
>
245
<h2>Animated Modal</h2>
246
</Modal>
247
```
248
249
## Accessibility
250
251
### Required Setup
252
253
```javascript
254
// Required: Set app element before using any modals
255
Modal.setAppElement('#root');
256
257
// Or with multiple elements
258
Modal.setAppElement([document.getElementById('root'), document.getElementById('menu')]);
259
```
260
261
### Accessibility Props
262
263
```javascript
264
<Modal
265
isOpen={modalIsOpen}
266
contentLabel="User Profile Dialog" // Required for screen readers
267
role="dialog" // Default, can be changed
268
ariaHideApp={true} // Default, hides background content
269
shouldFocusAfterRender={true} // Default, focuses modal on open
270
shouldReturnFocusAfterClose={true} // Default, returns focus on close
271
>
272
<h2 id="modal-title">User Profile</h2>
273
<div aria-describedby="modal-title">
274
Modal content here
275
</div>
276
</Modal>
277
```
278
279
## Event Handling
280
281
### Close Events
282
283
```javascript
284
function handleRequestClose(event) {
285
// event can be from ESC key or overlay click
286
console.log('Modal close requested:', event.type);
287
setModalIsOpen(false);
288
}
289
290
<Modal
291
isOpen={modalIsOpen}
292
onRequestClose={handleRequestClose}
293
shouldCloseOnOverlayClick={true} // Default
294
shouldCloseOnEsc={true} // Default
295
>
296
<h2>Closeable Modal</h2>
297
</Modal>
298
```
299
300
### Lifecycle Events
301
302
```javascript
303
function handleAfterOpen({ overlayEl, contentEl }) {
304
// Modal is now fully open and accessible
305
console.log('Modal opened', { overlayEl, contentEl });
306
}
307
308
function handleAfterClose() {
309
// Modal is completely closed and removed from DOM
310
console.log('Modal closed');
311
}
312
313
<Modal
314
isOpen={modalIsOpen}
315
onAfterOpen={handleAfterOpen}
316
onAfterClose={handleAfterClose}
317
>
318
<h2>Modal with Lifecycle Handlers</h2>
319
</Modal>
320
```
321
322
## Custom Elements
323
324
### Custom Overlay and Content
325
326
```javascript
327
const customOverlay = (props, contentEl) => (
328
<div {...props} className="custom-overlay">
329
{contentEl}
330
</div>
331
);
332
333
const customContent = (props, children) => (
334
<div {...props} className="custom-content">
335
<header>Modal Header</header>
336
<main>{children}</main>
337
<footer>Modal Footer</footer>
338
</div>
339
);
340
341
<Modal
342
isOpen={modalIsOpen}
343
overlayElement={customOverlay}
344
contentElement={customContent}
345
>
346
<p>Content goes in the main section</p>
347
</Modal>
348
```
349
350
## Animation and Transitions
351
352
### CSS Transitions
353
354
```javascript
355
<Modal
356
isOpen={modalIsOpen}
357
closeTimeoutMS={200} // Wait 200ms before unmounting
358
className={{
359
base: 'modal',
360
afterOpen: 'modal--after-open',
361
beforeClose: 'modal--before-close'
362
}}
363
>
364
<h2>Animated Modal</h2>
365
</Modal>
366
```
367
368
Corresponding CSS:
369
370
```css
371
.modal {
372
opacity: 0;
373
transition: opacity 200ms;
374
}
375
376
.modal--after-open {
377
opacity: 1;
378
}
379
380
.modal--before-close {
381
opacity: 0;
382
}
383
```
384
385
## Advanced Configuration
386
387
### Portal Customization
388
389
```javascript
390
<Modal
391
isOpen={modalIsOpen}
392
portalClassName="custom-portal"
393
parentSelector={() => document.getElementById('modal-root')}
394
bodyOpenClassName="body-modal-open"
395
htmlOpenClassName="html-modal-open"
396
>
397
<h2>Custom Portal Modal</h2>
398
</Modal>
399
```
400
401
### Refs and DOM Access
402
403
```javascript
404
let overlayRef;
405
let contentRef;
406
407
<Modal
408
isOpen={modalIsOpen}
409
overlayRef={ref => overlayRef = ref}
410
contentRef={ref => contentRef = ref}
411
onAfterOpen={() => {
412
// Direct DOM access available
413
console.log('Overlay element:', overlayRef);
414
console.log('Content element:', contentRef);
415
}}
416
>
417
<h2>Modal with Refs</h2>
418
</Modal>
419
```
420
421
### Testing Support
422
423
```javascript
424
<Modal
425
isOpen={modalIsOpen}
426
testId="user-profile-modal"
427
contentLabel="User Profile"
428
>
429
<h2>User Profile Modal</h2>
430
<p>This modal can be found by test frameworks using data-testid="user-profile-modal"</p>
431
</Modal>
432
```