Skip to content

Commit

Permalink
bugfix(react-dialog): fix scroll locking issues introduced by a regre…
Browse files Browse the repository at this point in the history
…ssion (microsoft#31377)
  • Loading branch information
bsunderhus authored and miroslavstastny committed Jun 14, 2024
1 parent 9541b03 commit 9030834
Show file tree
Hide file tree
Showing 5 changed files with 44 additions and 25 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "patch",
"comment": "bugfix: fix scroll locking issues introduced by a regression",
"packageName": "@fluentui/react-dialog",
"email": "bernardo.sunderhus@gmail.com",
"dependentChangeType": "patch"
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import * as React from 'react';
import { useControllableState, useEventCallback, useId, useIsomorphicLayoutEffect } from '@fluentui/react-utilities';
import { useControllableState, useEventCallback, useId } from '@fluentui/react-utilities';
import { useHasParentContext } from '@fluentui/react-context-selector';
import { useDisableBodyScroll, useFocusFirstElement } from '../../utils';
import { useFocusFirstElement } from '../../utils';
import { DialogContext } from '../../contexts';

import type { DialogOpenChangeData, DialogProps, DialogState } from './Dialog.types';
Expand Down Expand Up @@ -45,19 +45,6 @@ export const useDialog_unstable = (props: DialogProps): DialogState => {

const isNestedDialog = useHasParentContext(DialogContext);

const { disableBodyScroll, enableBodyScroll } = useDisableBodyScroll();
const isBodyScrollLocked = Boolean(open && modalType !== 'non-modal');
useIsomorphicLayoutEffect(() => {
if (isNestedDialog) {
return;
}
if (open && isBodyScrollLocked) {
disableBodyScroll();
} else {
enableBodyScroll();
}
}, [disableBodyScroll, enableBodyScroll, isBodyScrollLocked, isNestedDialog, open]);

return {
components: {
backdrop: 'div',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,13 @@ import {
isResolvedShorthand,
slot,
getIntrinsicElementProps,
useIsomorphicLayoutEffect,
} from '@fluentui/react-utilities';
import type { DialogSurfaceElement, DialogSurfaceProps, DialogSurfaceState } from './DialogSurface.types';
import { useDialogContext_unstable } from '../../contexts';
import { Escape } from '@fluentui/keyboard-keys';
import { useDialogTransitionContext_unstable } from '../../contexts/dialogTransitionContext';
import { useDisableBodyScroll } from '../../utils/useDisableBodyScroll';

/**
* Create the state required to render DialogSurface.
Expand All @@ -31,6 +33,7 @@ export const useDialogSurface_unstable = (
const dialogRef = useDialogContext_unstable(ctx => ctx.dialogRef);
const requestOpenChange = useDialogContext_unstable(ctx => ctx.requestOpenChange);
const dialogTitleID = useDialogContext_unstable(ctx => ctx.dialogTitleId);
const open = useDialogContext_unstable(ctx => ctx.open);

const handledBackdropClick = useEventCallback((event: React.MouseEvent<HTMLDivElement>) => {
if (isResolvedShorthand(props.backdrop)) {
Expand Down Expand Up @@ -70,6 +73,20 @@ export const useDialogSurface_unstable = (
if (backdrop) {
backdrop.onClick = handledBackdropClick;
}

const { disableBodyScroll, enableBodyScroll } = useDisableBodyScroll();
const isBodyScrollLocked = Boolean(open && modalType !== 'non-modal');
useIsomorphicLayoutEffect(() => {
if (isNestedDialog) {
return;
}
if (open && isBodyScrollLocked && transitionStatus === 'entering') {
disableBodyScroll();
} else if (transitionStatus === 'exited') {
enableBodyScroll();
}
}, [disableBodyScroll, enableBodyScroll, isBodyScrollLocked, isNestedDialog, open, transitionStatus]);

return {
components: { backdrop: 'div', root: 'div' },
backdrop,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,7 @@ export const useHTMLNoScrollStyles = makeResetStyles({
overflowY: ['hidden', 'clip'],
scrollbarGutter: 'stable',
});

export const useBodyNoScrollStyles = makeResetStyles({
overflowY: 'hidden',
});
Original file line number Diff line number Diff line change
@@ -1,37 +1,41 @@
import { useFluent_unstable } from '@fluentui/react-shared-contexts';
import { useCallback } from 'react';

import { useHTMLNoScrollStyles } from './useDisableBodyScroll.styles';
import { useBodyNoScrollStyles, useHTMLNoScrollStyles } from './useDisableBodyScroll.styles';

/**
* hook that disables body scrolling through `overflowY: hidden` CSS property
* @internal
* A React *hook* that disables body scrolling through `overflowY: hidden` CSS property
*/
export function useDisableBodyScroll(): {
disableBodyScroll: () => void;
enableBodyScroll: () => void;
} {
const htmlNoScrollStyle = useHTMLNoScrollStyles();
const htmlNoScrollStyles = useHTMLNoScrollStyles();
const bodyNoScrollStyles = useBodyNoScrollStyles();
const { targetDocument } = useFluent_unstable();

const disableBodyScroll = useCallback(() => {
if (!targetDocument) {
return;
}
const isScrollbarVisible =
(targetDocument.defaultView?.innerWidth ?? 0) > targetDocument.documentElement.clientWidth;
if (!isScrollbarVisible) {
const isHorizontalScrollbarVisible =
targetDocument.body.clientHeight > (targetDocument.defaultView?.innerHeight ?? 0);
if (!isHorizontalScrollbarVisible) {
return;
}
targetDocument.documentElement.classList.add(htmlNoScrollStyle);
targetDocument.documentElement.classList.add(htmlNoScrollStyles);
targetDocument.body.classList.add(bodyNoScrollStyles);
return;
}, [targetDocument, htmlNoScrollStyle]);
}, [targetDocument, htmlNoScrollStyles, bodyNoScrollStyles]);

const enableBodyScroll = useCallback(() => {
if (!targetDocument) {
return;
}
targetDocument.documentElement.classList.remove(htmlNoScrollStyle);
}, [targetDocument, htmlNoScrollStyle]);
targetDocument.documentElement.classList.remove(htmlNoScrollStyles);
targetDocument.body.classList.remove(bodyNoScrollStyles);
}, [targetDocument, htmlNoScrollStyles, bodyNoScrollStyles]);

return {
disableBodyScroll,
Expand Down

0 comments on commit 9030834

Please sign in to comment.