material-ui icon indicating copy to clipboard operation
material-ui copied to clipboard

[material-ui][Popover] Incorrect position inside CSS inline-size container

Open asrytis opened this issue 1 year ago • 4 comments

Steps to reproduce

Link to live example: https://codesandbox.io/p/sandbox/mui-container-query-wtzlg5?file=%2Fsrc%2FDemo.tsx

Steps:

  1. Tick the "Disable portal" checkbox
  2. Click the "Open popover" button

Current behavior

The popover is mispositioned when disablePortal flag is set

Expected behavior

The popover should be positioned the same regardless of the disablePortal flag

Context

In our app we have a reusable form field component that uses container queries for different layouts depending on available size. Some form fields use the MUI Popover component, eg. to display a calendar in a date input field.

Your environment

npx @mui/envinfo
  System:
    OS: macOS 14.3.1
  Binaries:
    Node: 19.6.0 - ~/.nvm/versions/node/v19.6.0/bin/node
    npm: 9.5.0 - ~/.nvm/versions/node/v19.6.0/bin/npm
    pnpm: 8.6.12 - ~/.nvm/versions/node/v19.6.0/bin/pnpm
  Browsers:
    Chrome: 121.0.6167.184
    Edge: Not Found
    Safari: 17.3.1```
</details>


**Search keywords**: mui popover inline size disableportal

asrytis avatar Feb 22 '24 09:02 asrytis

In the codesandbox example above you can see the popover is offset by exactly the amount of top padding outside the container.

The positioning of the popover breaks due to the fact that CSS containers seem to create a new stacking context. Therefore the popover container (.MuiPopover-root) no longer covers the whole screen but only the container:

Screenshot 2024-02-22 at 11 50 02

Edit: consequentially this also affects the outside click handler

asrytis avatar Feb 22 '24 09:02 asrytis

Thanks for reporting. It seems that the Material UI Popover component's positioning calculations don't account for the layout of containers. If the container has a type other than normal, the positioning should be relative to the container rather than the window.

In the future, Popover may be replaced by Popup from Base UI, which uses Floating UI internally and considers the containing blocks in its calculations. Here's an example demonstrating how Base UI Popup handles positioning correctly with inline-size container: https://stackblitz.com/edit/vitejs-vite-pvnhbj?file=src%2FApp.tsx.

I'll mark this as a bug though.

ZeeshanTamboli avatar Apr 29 '24 10:04 ZeeshanTamboli

Hi, .When the 'disable portal' option is unchecked, the popover (simple-popover) is rendered in the body as a direct child and sibling element of our app (#root).

.When the 'disable portal' option is checked, the popover (simple-popover) is rendered next to the 'Open Popover' button." please check the attached images

That's why ".presentation/simple-popover" is not taking the full width of the window.

disable-portal enable-portal

farhanmian avatar Apr 30 '24 04:04 farhanmian

That's why ".presentation/simple-popover" is not taking the full width of the window.

Even if it's rendered as a child, it has position: fixed and is positioned relative to the container. If there's no container, it is positioned relative to the browser window due to position: fixed.

ZeeshanTamboli avatar Apr 30 '24 09:04 ZeeshanTamboli