or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

tessl/npm-react-modal

Accessible modal dialog component for React.JS applications with comprehensive ARIA support and customization options.

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
npmpkg:npm/react-modal@3.16.x

To install, run

npx @tessl/cli install tessl/npm-react-modal@3.16.0

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

```