@@ -42,7 +42,7 @@ export interface RenderModalDialogProps {
4242 style : React . CSSProperties | undefined ;
4343 className : string | undefined ;
4444 tabIndex : number ;
45- role : string ;
45+ role : string | undefined ;
4646 ref : React . RefCallback < Element > ;
4747 'aria-modal' : boolean | undefined ;
4848}
@@ -184,6 +184,27 @@ export interface BaseModalProps extends TransitionCallbacks {
184184 restoreFocusOptions ?: {
185185 preventScroll : boolean ;
186186 } ;
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 ;
187208}
188209
189210export interface ModalProps extends BaseModalProps {
@@ -251,6 +272,9 @@ const Modal: React.ForwardRefExoticComponent<
251272 enforceFocus = true ,
252273 restoreFocus = true ,
253274 restoreFocusOptions,
275+ mountDialogOnEnter = true ,
276+ unmountDialogOnExit = true ,
277+ portal = true ,
254278 renderDialog,
255279 renderBackdrop = ( props : RenderModalBackdropProps ) => < div { ...props } /> ,
256280 manager : providedManager ,
@@ -349,10 +373,10 @@ const Modal: React.ForwardRefExoticComponent<
349373 // Show logic when:
350374 // - show is `true` _and_ `container` has resolved
351375 useEffect ( ( ) => {
352- if ( ! show || ! container ) return ;
376+ if ( ! show || ( ! container && portal ) ) return ;
353377
354378 handleShow ( ) ;
355- } , [ show , container , /* should never change: */ handleShow ] ) ;
379+ } , [ show , container , portal , /* should never change: */ handleShow ] ) ;
356380
357381 // Hide cleanup logic when:
358382 // - `exited` switches to true
@@ -419,15 +443,15 @@ const Modal: React.ForwardRefExoticComponent<
419443 onExited ?.( ...args ) ;
420444 } ;
421445
422- if ( ! container ) {
446+ if ( ! container && portal ) {
423447 return null ;
424448 }
425449
426450 const dialogProps = {
427- role,
451+ role : show ? role : undefined ,
428452 ref : modal . setDialogRef ,
429453 // apparently only works on the dialog role element
430- 'aria-modal' : role === 'dialog' ? true : undefined ,
454+ 'aria-modal' : show && role === 'dialog' ? true : undefined ,
431455 ...rest ,
432456 style,
433457 className,
@@ -446,8 +470,8 @@ const Modal: React.ForwardRefExoticComponent<
446470 transition as TransitionComponent ,
447471 runTransition ,
448472 {
449- unmountOnExit : true ,
450- mountOnEnter : true ,
473+ unmountOnExit : unmountDialogOnExit ,
474+ mountOnEnter : mountDialogOnEnter ,
451475 appear : true ,
452476 in : ! ! show ,
453477 onExit,
@@ -480,15 +504,18 @@ const Modal: React.ForwardRefExoticComponent<
480504 ) ;
481505 }
482506
483- return (
507+ return portal && container ? (
508+ ReactDOM . createPortal (
509+ < >
510+ { backdropElement }
511+ { dialog }
512+ </ > ,
513+ container ,
514+ )
515+ ) : (
484516 < >
485- { ReactDOM . createPortal (
486- < >
487- { backdropElement }
488- { dialog }
489- </ > ,
490- container ,
491- ) }
517+ { backdropElement }
518+ { dialog }
492519 </ >
493520 ) ;
494521 } ,
0 commit comments