Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ModalManager] Dialog in Shadow DOM creates scroll jump #39636

Open
2 tasks done
arminbashizade opened this issue Oct 27, 2023 · 6 comments 路 May be fixed by #40211
Open
2 tasks done

[ModalManager] Dialog in Shadow DOM creates scroll jump #39636

arminbashizade opened this issue Oct 27, 2023 · 6 comments 路 May be fixed by #40211
Assignees
Labels
bug 馃悰 Something doesn't work component: dialog This is the name of the generic UI component, not the React module!

Comments

@arminbashizade
Copy link

arminbashizade commented Oct 27, 2023

Duplicates

  • I have searched the existing issues

Latest version

  • I have tested the latest version

Steps to reproduce 馃暪

Link to live example:
https://stackblitz.com/edit/react-aj5fcw?file=index.tsx

Steps:

  1. add a dialog using Dialog demo
  2. add the same dialog in a Shadow DOM following steps from the docs
  3. add lots of divs to create overflow
  4. open the two dialogs and see the difference in handling the scrollbar

Current behavior 馃槸

when the dialog is opened in Shadow DOM the scrollbar is removed (overflow: hidden) however the space is not filled with a padding-right, as it is done for a dialog outside of shadow DOM, see the column of text on the right on the example:

image

Expected behavior 馃

the scrollbar's width must be replaced with a padding-right

Context 馃敠

We use Shadow DOM to isolate styles for components we inject into other pages. We add a component on a long page that opens a dialog, but because its added in a Shadow DOM it doesn't replace the scrollbar width with padding so there's a jump on the page.

here's where I think the issue is happening in MUI:
In ModalManager isOverflowin function returns false because container is not the same as body and both its clientHeight and scrollHeight are 0

function isOverflowing(container: Element): boolean {
const doc = ownerDocument(container);
if (doc.body === container) {
return ownerWindow(container).innerWidth > doc.documentElement.clientWidth;
}
return container.scrollHeight > container.clientHeight;
}

so handleContainer will not add paddingRight

if (isOverflowing(container)) {
// Compute the size before applying overflow hidden to avoid any scroll jumps.
const scrollbarSize = getScrollbarSize(ownerDocument(container));
restoreStyle.push({
value: container.style.paddingRight,
property: 'padding-right',
el: container,
});
// Use computed style, here to get the real padding to add our scrollbar width.
container.style.paddingRight = `${getPaddingRight(container) + scrollbarSize}px`;
// .mui-fixed is a global helper.
const fixedElements = ownerDocument(container).querySelectorAll('.mui-fixed');
[].forEach.call(fixedElements, (element: HTMLElement | SVGElement) => {
restoreStyle.push({
value: element.style.paddingRight,
property: 'padding-right',
el: element,
});
element.style.paddingRight = `${getPaddingRight(element) + scrollbarSize}px`;
});
}

Your environment 馃寧

npx @mui/envinfo
  System:
    OS: Windows 10 10.0.22621
  Binaries:
    Node: 18.18.0 - C:\Program Files\nodejs\node.EXE
    Yarn: 1.22.19 - ~\AppData\Roaming\npm\yarn.CMD
    npm: 9.8.1 - C:\Program Files\nodejs\npm.CMD
  Browsers:
    Chrome: 118.0.5993.117
    Edge: Chromium (118.0.2088.69)
  npmPackages:
    @emotion/react:  11.11.1
    @emotion/styled:  11.11.0
    @mui/base:  5.0.0-beta.21
    @mui/codemod:  5.14.15
    @mui/core-downloads-tracker:  5.14.15
    @mui/docs:  5.14.15
    @mui/envinfo:  2.0.12
    @mui/icons-material:  5.14.15
    @mui/internal-waterfall:  1.0.0
    @mui/joy:  5.0.0-beta.12
    @mui/lab:  5.0.0-alpha.150
    @mui/markdown:  5.0.0
    @mui/material:  5.14.15
    @mui/material-next:  6.0.0-alpha.107
    @mui/private-theming:  5.14.15
    @mui/styled-engine:  5.14.15
    @mui/styled-engine-sc:  6.0.0-alpha.3
    @mui/styles:  5.14.15
    @mui/system:  5.14.15
    @mui/types:  7.2.7
    @mui/utils:  5.14.15
    @mui/x-charts:  6.0.0-alpha.15
    @mui/x-data-grid:  6.16.2
    @mui/x-data-grid-generator:  6.16.2
    @mui/x-data-grid-premium:  6.16.2
    @mui/x-data-grid-pro:  6.16.2
    @mui/x-date-pickers:  6.16.2
    @mui/x-date-pickers-pro:  6.16.2
    @mui/x-license-pro:  6.10.2
    @mui/x-tree-view:  6.0.0-alpha.1
    @mui/zero-jest:  0.0.1-alpha.0
    @mui/zero-next-plugin:  0.0.1-alpha.0
    @mui/zero-runtime:  0.0.1-alpha.0
    @mui/zero-tag-processor:  0.0.1-alpha.0
    @mui/zero-vite-plugin:  0.0.1-alpha.0
    @types/react: ^18.2.32 => 18.2.33
    react:  18.2.0
    react-dom:  18.2.0
    styled-components:  6.0.8
    typescript: ^5.1.6 => 5.1.6

this was tested in Chrome

@arminbashizade arminbashizade added the status: waiting for maintainer These issues haven't been looked at yet by a maintainer label Oct 27, 2023
@zannager zannager added the component: dialog This is the name of the generic UI component, not the React module! label Oct 27, 2023
@mnajdova mnajdova assigned michaldudak and unassigned siriwatknp Nov 8, 2023
@michaldudak michaldudak added bug 馃悰 Something doesn't work and removed status: waiting for maintainer These issues haven't been looked at yet by a maintainer labels Nov 24, 2023
@michaldudak
Copy link
Member

@arminbashizade, thanks for the report. Would you like to create a PR with a fix?

@michaldudak michaldudak removed their assignment Nov 24, 2023
@arminbashizade arminbashizade linked a pull request Dec 15, 2023 that will close this issue
1 task
@radist2s
Copy link

@michaldudak, I have encountered a similar problem as @arminbashizade. According to documentation, container is the way to set <Dialog/>'s root when using Shadow DOM.
The problem, as I see it, is the impossibility of controlling which scrollbar to lock when using a custom container:

let scrollContainer: HTMLElement;
if (container.parentNode instanceof DocumentFragment) {
scrollContainer = ownerDocument(container).body;
} else {
// Support html overflow-y: auto for scroll stability between pages
// https://css-tricks.com/snippets/css/force-vertical-scrollbar/
const parent = container.parentElement;
const containerWindow = ownerWindow(container);
scrollContainer =
parent?.nodeName === 'HTML' &&
containerWindow.getComputedStyle(parent).overflowY === 'scroll'
? parent
: container;
}

The only way to solve the problem is to use disableScrollLock and try to implement custom scrollbar locking logic, but this is not reliable.

@michaldudak, if <Modal/> would accept something like scrollContainer as a property, that would solve the problem. However, I realize that extending the API without a dire need is unwise. Maybe you can suggest how to solve the problem differently? I could prepare a PR.

@michaldudak
Copy link
Member

We're not adding any new features to this version of @mui/base. We moved the development of the library to the new repo, and we're working on changing the components' API there. When we get to the Modal, we'll consider this issue.

@TamirCode
Copy link

TamirCode commented May 10, 2024

I have an issue when using LightGallery's carousel component along with MUI Dialogs on the same page,
opening the MUI dialog causes scroll to jump to bottom of page
When using modal component instead, the scroll jumps to the Carousel component

@michaldudak
Copy link
Member

@TamirCode, please open a new issue and provide a reproduction.

@TamirCode
Copy link

@TamirCode, please open a new issue and provide a reproduction.

it seems to be an issue with lightgallery package rather than mui, my mistake. thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug 馃悰 Something doesn't work component: dialog This is the name of the generic UI component, not the React module!
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants