davidjerleke / embla-carousel

A lightweight carousel library with fluid motion and great swipe precision.
https://www.embla-carousel.com
MIT License
5.91k stars 178 forks source link

[Solved] When opening the Dialog of material-UI, the screen will jump #211

Closed Dylan0916 closed 3 years ago

Dylan0916 commented 3 years ago

Bug is related to

Embla Carousel version

Describe the bug

When opening the Dialog of material-UI, the screen will jump

CodeSandbox

I forked from https://codesandbox.io/s/embla-carousel-default-react-88p7h

Steps to reproduce

  1. Click the 'Click it first' button.
  2. Click the 'open dialog' button.
  3. Click on the background to close the dialog.
  4. The screen will jump to the top.

Expected behavior

Additional context

davidjerleke commented 3 years ago

Hi @Dylan0916,

Thank you for creating this issue. This is happening because the Dialog of material-UI will restore focus on the last element that was focused before the modal opened. And you might think: Ok, but the last element that should have focus should be the button that I just clicked, the one that opens the modal?

Why this is happening

Not in this case, because Embla Carousel calls event.preventDefault() on the mousedown and touchstart event which also prevents the button from receiving focus. And Embla has to to this, because it locks the intersecting scroll axis while you're dragging the carousel. For example, if you have a carousel that scrolls horizontally, along the X axis, it prevents the browser from scrolling the Y axis. So this is by design. Scrolling a carousel on mobile device that allows you to scroll the website at the same time have the most horrible UX I can think of.

Solving the problem

So I can think of two solutions. The first being:

<button
  style={{ position: "absolute" }}
  onClick={(event) => {
    if (embla.clickAllowed()) event.currentTarget.focus(); // Programmatically focus on this button when clicked and not dragged
    setOpen(true);
  }}
>
  open dialog
</button>

And the second solution:

<MuiDialog
  open={open}
  onClose={() => setOpen(false)}
  disableRestoreFocus={true} // Add this and the dialog won't restore the focus to the last focused element when it's closed
>
  123
</MuiDialog>

I hope this helps.

Cheers, David

Dylan0916 commented 3 years ago

Hi @Dylan0916,

Thank you for creating this issue. This is happening because the Dialog of material-UI will restore focus on the last element that was focused before the modal opened. And you might think: Ok, but the last element that should have focus should be the button that I just clicked, the one that opens the modal?

Hi, Thank you very much for your quick reply.

Your answer is very helpful to me, I'll close this issue.

Best.