Skip to content

Commit

Permalink
Fix and enhance body class attribute effect
Browse files Browse the repository at this point in the history
  • Loading branch information
stokesman committed Dec 20, 2023
1 parent 5441005 commit 3da7637
Showing 1 changed file with 17 additions and 15 deletions.
32 changes: 17 additions & 15 deletions packages/components/src/modal/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,12 @@ import StyleProvider from '../style-provider';
import type { ModalProps } from './types';

// Used to track and dismiss the prior modal when another opens unless nested.
const level0Dismissers: MutableRefObject<
ModalProps[ 'onRequestClose' ] | undefined
>[] = [];
const ModalContext = createContext( level0Dismissers );
const ModalContext = createContext<
MutableRefObject< ModalProps[ 'onRequestClose' ] | undefined >[]
>( [] );

let isBodyOpenClassActive = false;
// Used to track body class names applied while modals are open.
const bodyOpenClasses = new Map< string, number >();

function UnforwardedModal(
props: ModalProps,
Expand Down Expand Up @@ -146,7 +146,7 @@ function UnforwardedModal(
// one should remain open at a time and the list enables closing prior ones.
const dismissers = useContext( ModalContext );
// Used for the tracking and dismissing any nested modals.
const nestedDismissers = useRef< typeof level0Dismissers >( [] );
const nestedDismissers = useRef< typeof dismissers >( [] );

// Updates the stack tracking open modals at this level and calls
// onRequestClose for any prior and/or nested modals as applicable.
Expand All @@ -162,20 +162,22 @@ function UnforwardedModal(
};
}, [ dismissers ] );

const isLevel0 = dismissers === level0Dismissers;
// Adds/removes the value of bodyOpenClassName to body element.
useEffect( () => {
if ( ! isBodyOpenClassActive ) {
isBodyOpenClassActive = true;
document.body.classList.add( bodyOpenClassName );
}
const theClass = bodyOpenClassName;
const oneMore = 1 + ( bodyOpenClasses.get( theClass ) ?? 0 );
bodyOpenClasses.set( theClass, oneMore );
document.body.classList.add( bodyOpenClassName );
return () => {
if ( isLevel0 && dismissers.length === 0 ) {
document.body.classList.remove( bodyOpenClassName );
isBodyOpenClassActive = false;
const oneLess = bodyOpenClasses.get( theClass )! - 1;
if ( oneLess === 0 ) {
document.body.classList.remove( theClass );
bodyOpenClasses.delete( theClass );
} else {
bodyOpenClasses.set( theClass, oneLess );
}
};
}, [ bodyOpenClassName, dismissers, isLevel0 ] );
}, [ bodyOpenClassName ] );

// Calls the isContentScrollable callback when the Modal children container resizes.
useLayoutEffect( () => {
Expand Down

0 comments on commit 3da7637

Please sign in to comment.