mui / material-ui

Material UI: Comprehensive React component library that implements Google's Material Design. Free forever.
https://mui.com/material-ui/
MIT License
93.96k stars 32.27k forks source link

[joy-ui][Select] Scroll-jumping when clicking Select element in responsive mode #39113

Open RonaldRuckus opened 1 year ago

RonaldRuckus commented 1 year ago

Duplicates

Latest version

Steps to reproduce 🕹

Link to live example:

https://streamable.com/7854lm

Steps:

  1. Create a Select element with Options.
  2. Turn on responsive mode w/ Touch Actions in Firefox / Chromium
  3. Give/Allow the Select element a width greater than ~60vw. 100vw is best as it scales.
  4. Ensure that the vertical viewport is long enough to enable scrolling
  5. Ensure that the Select element has a large offset from the top
  6. Scroll down to the Select element
  7. Click the Select element and notice the following a. The scroll will jump upwards depending on the set width b. On chromium the width will cause an overflow and a horizontal scrollbar will appear EVEN THOUGH NO ELEMENTS ARE OVERFLOWING ba. For some reason with a setting of "overflow-x: hidden" on the HTML element on Firefox the horizontal scrollbar will appear as well bb. For fun, if you highlight the element in DevTools and cause a re-calculation it will slowly return back to normal
const _Main = () =>
    <>
        <div style={{ height: "600px" }} />
        <Select defaultValue="dog">
            <Option value="dog">Dog</Option>
            <Option value="cat">Cat</Option>
        </Select>
        <div style={{ height: "600px" }} />
    </>

(For me only) 8. Spend countless hours trying to understand what the heck is going on.

The issue comes back to the Touch Actions. Turning it off resolves the issue. Would love to know what causes this though.

I chalked it up to the horizontal overflow appearing and rapidly disappearing, causing the jump in the vertical positioning. If that makes sense. Mainly because the size of the jump depended on the width of the element.

If it means anything it seems to follow the formula of: bodyScrollWidth = selectElementWidth * 1.5 - 29. With a viewport of 387 x 878. The element had a height of 28 (+2 from border). So, not sure where the 29 or 1.5x comes from. But I was always able to predict what the scrollWidth would be using this formula

Current behavior 😯

Firefox:

Chromium:

Expected behavior 🤔

Should be normal

Context 🔦

In the video I actually tested this using the MUI website to confirm it wasn't something strange in my environment.

I just hope someone else doesn't fall into this issue and waste a bunch of hours like I did.

Your environment 🌎

I used the MUI website as seen in the video and tested on Firefox + Chromium Firefox: 113.0.1 (64-bit) Chromium: 117.0.5938.88 (Official Build) snap (64-bit)
pixelass commented 1 year ago

This happens on both: Mobile AND Mobile (no touch) It does not happen on Desktop OR Desktop (touch)

Statements above apply for the same viewport size

image

pixelass commented 1 year ago

Here's a new Video (the one from OP is not available anymore) Also a repro Sandbox (open in standalone tab and enable responsive view at iPhone SE or similar small screens)

https://codesandbox.io/s/joy-ui-select-overflow-nl4n57?file=/src/App.js Direct Link to standalone: https://nl4n57.csb.app/

https://github.com/mui/material-ui/assets/1148334/18dbf344-087c-4062-aeb3-225799209385

pixelass commented 1 year ago

Additional note:

My html and body have overflow:hidden (the repro sandbox does not)
As already mentioned by @RonaldRuckus the issue resolves when hovering any element in the DOM inspector.

I prepared a listBoxOpen: true version which also illustrates the issue. There is definitely something strange going on (see inital jump and jump on interaction in the screen-recording)

Standalone: https://gz8v9l.csb.app/
Sandbox: https://codesandbox.io/s/joy-ui-select-overflow-forked-gz8v9l?file=/src/App.js

https://github.com/mui/material-ui/assets/1148334/f1807c8b-d24b-4d41-9bfd-ea0b158a9cb6

pixelass commented 1 year ago

⚠️ Important Note: I just checked the examples from above on my iPhone 12 mini and could not reproduce the jump or overflow) It might just be a bug in the browser implementation of touch mocking.

In my case the select is in a Modal. I am not sure if that is related. Overscroll (but no jump) also happens here (from original Jouy-UI docs): https://5r5vs6.csb.app/

I looked at the styles and noticed that the ModalDialog uses 100vw which is know to cause issues and IMHO should never be used since scrollbars are not respected in 100vw. This lead me to some testing. I adjusted the styles of the ModalDialog to use max (I know this breaks the intent) in combination with 100% instead of 100vw.

Only the combination of max AND 100% fixes this

With this change the overflow goes away, but there is a strange gap (see screen-recording) and the Layout off the dialog is oviously broken due to the width hack.

Sandbox: https://codesandbox.io/s/joy-ui-select-overflow-forked-6djjtr?file=/src/App.js Standalone: https://6djjtr.csb.app/

Before

<ModalDialog sx={{
  minWidth: `min(calc(100vw - 2 * var(--Card-padding)), var(--ModalDialog-minWidth, 300px))`,
}}>

After

<ModalDialog sx={{
  minWidth: `max(calc(100% - 2 * var(--Card-padding)), var(--ModalDialog-minWidth, 300px))`,
}}>

https://github.com/mui/material-ui/assets/1148334/69f90f08-5a5f-4706-9eb9-e182f5b81203

RonaldRuckus commented 1 year ago

Thanks for adding a new video, sandbox, and information.

I have noticed this actually happens on my phone as well. A Pixel 7. I believe it's an issue with how the options are rendered.

There is a transform applied to place it beneath the select element and for whatever reason it confuses the browser. Would really like to get this resolved.

siriwatknp commented 1 year ago

https://codesandbox.io/s/joy-ui-select-overflow-nl4n57?file=/src/App.js Direct Link to standalone: https://nl4n57.csb.app/

I can reproduce the issue but cannot figure out the root cause yet.

pixelass commented 1 year ago

Just an idea. Maybe it's related to finding the perfect placement for the dropdown. Haven't tested. It was just a thought I had and wanted to share

Alexandre-Herve commented 11 months ago

I also faced the described horizontal overflow issue on Chromium with a Select in a Modal. If this can help someone, adding width: '100%' to the listbox fixed it for me: the listbox doesn't overflow anymore.

<Select                                                                                                                                                                                                                        
  slotProps={{                                                                        
    listbox: {                                                                        
      sx: {                                                                           
        width: '100%',     // <- this                                                           
      },                                                                              
    },                                                                                
  }}                                                                                  
>                                                                                     
  [...]                                                
</Select>

Before:

image

After:

image
danielbattat commented 3 months ago
    width: '100%',     // <- this                                                           

This didn't work for me, but the following did:

<Select                                                                                                                                                                                                                        
  slotProps={{                                                                        
    listbox: {                                                                        
      sx: {                                                                           
        minwidth: 'unset',     // <- this                                                           
      },                                                                              
    },                                                                                
  }}                                                                                  
>                                                                                     
  [...]                                                
</Select>
viniciosComerciante commented 1 week ago

I also faced the described horizontal overflow issue on Chromium with a Select in a Modal. If this can help someone, adding width: '100%' to the listbox fixed it for me: the listbox doesn't overflow anymore.

<Select                                                                                                                                                                                                                        
  slotProps={{                                                                        
    listbox: {                                                                        
      sx: {                                                                           
        width: '100%',     // <- this                                                           
      },                                                                              
    },                                                                                
  }}                                                                                  
>                                                                                     
  [...]                                                
</Select>

Before: image

After: image

Tks man.