@@ -42,7 +42,7 @@ export interface RenderModalDialogProps {
42
42
style : React . CSSProperties | undefined ;
43
43
className : string | undefined ;
44
44
tabIndex : number ;
45
- role : string ;
45
+ role : string | undefined ;
46
46
ref : React . RefCallback < Element > ;
47
47
'aria-modal' : boolean | undefined ;
48
48
}
@@ -184,6 +184,27 @@ export interface BaseModalProps extends TransitionCallbacks {
184
184
restoreFocusOptions ?: {
185
185
preventScroll : boolean ;
186
186
} ;
187
+
188
+ /**
189
+ * Lazy mount the dialog element when the Modal is shown.
190
+ *
191
+ * @default true
192
+ */
193
+ mountDialogOnEnter ?: boolean | undefined ;
194
+
195
+ /**
196
+ * Unmount the dialog element (remove it from the DOM) when the modal is no longer visible.
197
+ *
198
+ * @default true
199
+ */
200
+ unmountDialogOnExit ?: boolean | undefined ;
201
+
202
+ /**
203
+ * Render modal in a portal.
204
+ *
205
+ * @default true
206
+ */
207
+ portal ?: boolean | undefined ;
187
208
}
188
209
189
210
export interface ModalProps extends BaseModalProps {
@@ -251,6 +272,9 @@ const Modal: React.ForwardRefExoticComponent<
251
272
enforceFocus = true ,
252
273
restoreFocus = true ,
253
274
restoreFocusOptions,
275
+ mountDialogOnEnter = true ,
276
+ unmountDialogOnExit = true ,
277
+ portal = true ,
254
278
renderDialog,
255
279
renderBackdrop = ( props : RenderModalBackdropProps ) => < div { ...props } /> ,
256
280
manager : providedManager ,
@@ -349,10 +373,10 @@ const Modal: React.ForwardRefExoticComponent<
349
373
// Show logic when:
350
374
// - show is `true` _and_ `container` has resolved
351
375
useEffect ( ( ) => {
352
- if ( ! show || ! container ) return ;
376
+ if ( ! show || ( ! container && portal ) ) return ;
353
377
354
378
handleShow ( ) ;
355
- } , [ show , container , /* should never change: */ handleShow ] ) ;
379
+ } , [ show , container , portal , /* should never change: */ handleShow ] ) ;
356
380
357
381
// Hide cleanup logic when:
358
382
// - `exited` switches to true
@@ -419,15 +443,15 @@ const Modal: React.ForwardRefExoticComponent<
419
443
onExited ?.( ...args ) ;
420
444
} ;
421
445
422
- if ( ! container ) {
446
+ if ( ! container && portal ) {
423
447
return null ;
424
448
}
425
449
426
450
const dialogProps = {
427
- role,
451
+ role : show ? role : undefined ,
428
452
ref : modal . setDialogRef ,
429
453
// apparently only works on the dialog role element
430
- 'aria-modal' : role === 'dialog' ? true : undefined ,
454
+ 'aria-modal' : show && role === 'dialog' ? true : undefined ,
431
455
...rest ,
432
456
style,
433
457
className,
@@ -446,8 +470,8 @@ const Modal: React.ForwardRefExoticComponent<
446
470
transition as TransitionComponent ,
447
471
runTransition ,
448
472
{
449
- unmountOnExit : true ,
450
- mountOnEnter : true ,
473
+ unmountOnExit : unmountDialogOnExit ,
474
+ mountOnEnter : mountDialogOnEnter ,
451
475
appear : true ,
452
476
in : ! ! show ,
453
477
onExit,
@@ -480,15 +504,18 @@ const Modal: React.ForwardRefExoticComponent<
480
504
) ;
481
505
}
482
506
483
- return (
507
+ return portal && container ? (
508
+ ReactDOM . createPortal (
509
+ < >
510
+ { backdropElement }
511
+ { dialog }
512
+ </ > ,
513
+ container ,
514
+ )
515
+ ) : (
484
516
< >
485
- { ReactDOM . createPortal (
486
- < >
487
- { backdropElement }
488
- { dialog }
489
- </ > ,
490
- container ,
491
- ) }
517
+ { backdropElement }
518
+ { dialog }
492
519
</ >
493
520
) ;
494
521
} ,
0 commit comments