Mitchy
Mitchy

Reputation: 145

Layout unexpectedly scroll jumps upon adding new html element when using MUI Menu

I have a simple html layout with Button connected to Mui Menu and i want to add a div above the Button. Like in this short example:

<div id='initially-not-rendered-div'
 style={{ height: "50px", width: "200px", backgroundColor: "blue" }}
/>
<Button>
        Dashboard
</Button>
<Menu>
    <MenuItem></MenuItem>
    <MenuItem></MenuItem>
</Menu>

If the Menu Button is partitially off the screen as in this picture:

Layout before shifting

the Menu causes screen to scroll up a little so the Button is fully visible.

My problem is, that when i add a div above the Menu after the scroll and then i close the Menu it makes the screen scroll jump very far away in most cases somewhere to the middle of the screen as you can see there:

enter image description here

You can try the full problem example here. Just scroll the button as shown in first picture, click it and close the menu.

Tested on Google Chrome.

I tried fixing it by using

event.preventDefault(); event.stopPropagation();

on all the click events in my code (as you could see in the codesandbox link) but it didnt help.

How can i get rid of this automatic scrolling behaviour caused by Menu?

Upvotes: 3

Views: 620

Answers (1)

Pandaiolo
Pandaiolo

Reputation: 11586

This is interesting!

I first suspected a focus related scenario:

  1. Click
  2. New element appears, pushing the button outside of viewport
  3. The menu is closed
  4. MUI restores focus on button, which is brought back in the viewport center

However, even after adding focus related props from Popover and Modal component (available in Menu... such as disableRestoreFocus) it did not change anything. Maybe I'm doing it wrong.

Anyway, I found a workaround that:

  1. Works (avoids the big scrolling on close)
  2. Improves UX by limiting unwanted scroll (and does not mess with accessibility)

The workaround is to scroll back the page by the added element height BEFORE closing the menu

  const handleClose = (e) => {
    if (!showNewEl) {
      setShowNewEl(true);
      window.document.documentElement.scrollTop += HEIGHT;
    }
    setAnchorEl(null);
  };

Here is a fork of your sandbox demonstrating the above: https://codesandbox.io/s/so-answer1-vm4pjk?file=/Demo.js

Upvotes: 1

Related Questions