diff --git a/src/components/dialog/Dialog.stories.mdx b/src/components/dialog/Dialog.stories.mdx
index deb957646..92765961d 100644
--- a/src/components/dialog/Dialog.stories.mdx
+++ b/src/components/dialog/Dialog.stories.mdx
@@ -517,6 +517,10 @@ import {fireEvent, within} from '@testing-library/react';
const handleDismissAnother = () => {
setAnotherOpen(false);
};
+ const handleCloseAll = () => {
+ setAnotherOpen(false);
+ setOpen(false);
+ };
const headerId = 'dialog-header';
const anotherHeaderId = 'another-dialog-header';
return (
@@ -583,7 +587,9 @@ import {fireEvent, within} from '@testing-library/react';
-
+
diff --git a/src/components/dialog/Dialog.tsx b/src/components/dialog/Dialog.tsx
index b0f4df001..35136708b 100644
--- a/src/components/dialog/Dialog.tsx
+++ b/src/components/dialog/Dialog.tsx
@@ -106,7 +106,7 @@ function BaseDialog({
const [isDialogHigherThanOverlay, setIsDialogHigherThanOverlay] =
React.useState(false);
const hasAnimations = supportsTransitions() && motionPreset !== 'none';
- const cleanupBodyNoScroll = useBodyNoScroll();
+ const cleanupBodyNoScroll = useBodyNoScroll(overlayRef);
const fireTransitionEndCallbacks = React.useCallback(() => {
setHasFinishedTransition(true);
diff --git a/src/components/dialog/useBodyNoScroll.ts b/src/components/dialog/useBodyNoScroll.ts
index 15ef088f5..8ce076d98 100644
--- a/src/components/dialog/useBodyNoScroll.ts
+++ b/src/components/dialog/useBodyNoScroll.ts
@@ -3,13 +3,24 @@ import * as React from 'react';
const NO_SCROLL_CLASS = 'sg-dialog-no-scroll';
const DIALOG_SELECTOR = '.js-dialog';
-export function useBodyNoScroll() {
+export function useBodyNoScroll(overlayRef: {current: HTMLDivElement | null}) {
const cleanupRef = React.useRef(null);
const forceCleanup = React.useCallback(() => {
if (cleanupRef.current) cleanupRef.current();
}, []);
React.useEffect(() => {
+ // @todo Use React Context API for detecting nested components
+ // https://github.com/brainly/style-guide/issues/2795
+ const isNestedDialog =
+ overlayRef.current?.parentElement?.closest(DIALOG_SELECTOR);
+
+ if (isNestedDialog) {
+ // if dialog is nested, this logic was already fired by parent dialog
+ // it prevents an issue with no cleanup when nested dialogs
+ return;
+ }
+
const body = document.body;
const scrollY = window.scrollY;
@@ -20,8 +31,18 @@ export function useBodyNoScroll() {
const cleanup = () => {
// it can only be forced once
cleanupRef.current = null;
- const manyDialogsOpened =
- document.querySelectorAll(DIALOG_SELECTOR).length > 1;
+
+ const dialogsOpenCount =
+ document.querySelectorAll(DIALOG_SELECTOR).length;
+ const nestedOpenDialogsCount =
+ overlayRef.current?.querySelectorAll(DIALOG_SELECTOR).length | 0;
+
+ // nested dialogs shouldn't be counted
+ // as a parent for nested dialogs, this particular one should perfrom the cleanup
+ const notNestedDialogsOpenCount =
+ dialogsOpenCount - nestedOpenDialogsCount;
+
+ const manyDialogsOpened = notNestedDialogsOpenCount > 1;
if (manyDialogsOpened) {
return;
@@ -34,6 +55,6 @@ export function useBodyNoScroll() {
cleanupRef.current = cleanup;
return cleanup;
- }, []);
+ }, [overlayRef]);
return forceCleanup;
}