diff --git a/packages/core/src/components/Modal/Modal.tsx b/packages/core/src/components/Modal/Modal.tsx index 4b81f23585..cebedb77b2 100644 --- a/packages/core/src/components/Modal/Modal.tsx +++ b/packages/core/src/components/Modal/Modal.tsx @@ -76,6 +76,10 @@ export interface ModalProps { * z-index attribute of the container */ zIndex?: number; + /** + * If true, the modal will unmount when it's not shown + */ + unmountOnClose?: boolean; } const Modal: FC & { width?: typeof ModalWidth } = ({ @@ -95,6 +99,7 @@ const Modal: FC & { width?: typeof ModalWidth } = ({ closeButtonAriaLabel = "Close", contentSpacing = false, zIndex = 10000, + unmountOnClose, "data-testid": dataTestId }) => { const childrenArray: ReactElement[] = useMemo( @@ -118,7 +123,7 @@ const Modal: FC & { width?: typeof ModalWidth } = ({ useBodyScrollLock({ instance }); // show/hide and animate the modal - useShowHideModal({ + const { shouldShow } = useShowHideModal({ instance, show, triggerElement, @@ -187,6 +192,9 @@ const Modal: FC & { width?: typeof ModalWidth } = ({ document.body ); + if (unmountOnClose && !shouldShow) { + return null; + } return ReactDOM.createPortal(dialog, document.body); }; diff --git a/packages/core/src/components/Modal/useShowHideModal.ts b/packages/core/src/components/Modal/useShowHideModal.ts index 0498c64d5a..c75cd05103 100644 --- a/packages/core/src/components/Modal/useShowHideModal.ts +++ b/packages/core/src/components/Modal/useShowHideModal.ts @@ -1,4 +1,4 @@ -import React, { useCallback, useEffect } from "react"; +import React, { useState, useCallback, useEffect } from "react"; import useAnimationProps from "./useAnimationProps"; import useKeyEvent from "../../hooks/useKeyEvent/index"; import { A11yDialogType } from "./ModalHelper"; @@ -19,6 +19,7 @@ export default function useShowHideModal({ onClose: () => void; alertDialog: boolean; }) { + const [isAnimating, setIsAnimating] = useState(false); const getAnimationProps = useAnimationProps(triggerElement, instance); const closeOnEsc = useCallback( @@ -37,22 +38,28 @@ export default function useShowHideModal({ keys: KEYS }); - // show/hide and animate the modal useEffect(() => { - if (!instance) { - return; - } - const animate = instance?.$el.childNodes[1].animate; if (show) { + setIsAnimating(true); instance?.show(); - if (animate) instance?.$el.childNodes[1].animate?.(...getAnimationProps()); + const animate = instance?.$el.childNodes[1].animate; + if (animate) { + instance?.$el.childNodes[1].animate?.(...getAnimationProps()); + } } else { + const animate = instance?.$el.childNodes[1].animate; if (animate) { const animation = instance?.$el.childNodes[1]?.animate(...getAnimationProps(true)); - animation?.finished.then(() => instance?.hide()); + animation?.finished.then(() => { + setIsAnimating(false); + instance?.hide(); + }); } else { + setIsAnimating(false); instance?.hide(); } } }, [show, instance, getAnimationProps]); + + return { shouldShow: isAnimating }; }