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’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Autocomplete] Autocomplete Popper position breaks when container height changes #44797

Open
IvanLuchkin opened this issue Dec 17, 2024 · 2 comments
Labels
component: autocomplete This is the name of the generic UI component, not the React module! package: material-ui Specific to @mui/material waiting for 👍 Waiting for upvotes

Comments

@IvanLuchkin
Copy link

IvanLuchkin commented Dec 17, 2024

Steps to reproduce

Steps:

  1. Open this link to live example: https://codesandbox.io/p/sandbox/fnxpf9
  2. Choose at least one of the options in the Autocomplete
  3. Autocomplete's Popper's position is not recalculated properly

Important: The issue can only be observed if disableCloseOnSelect is set to true

Current behavior

Popper position stays the same and does not follow the input. When a condition is met that collapse is retracting, popper's position gets recalculated to the where it should have been on the previous render

Expected behavior

Popper should "stick" to Autocomplete input no matter the Autocomplete position

Context

I am aware of the fact that Popper's position for Autocomplete is always 'fixed'. I have tried to use slotProps to set transition: true for the popper, but it causes it to default to top left position of the screen regardless of anchorEl if disablePortal=true. It also starts throwing warnings that "Empty string was passed to getElementById" from useAutocomplete.ts (which I'm not using).

The reason I was trying to use the transition prop is that from my many attempts to fix this, I've got one case where it did fix the issue, but I could not reproduce it since then. In any case this is very frustrating.

Browsers: Firefox, Chromium

Your environment

npx @mui/envinfo
System:
    OS: Linux 6.11 Manjaro Linux
  Binaries:
    Node: 20.11.1 - ~/.nvm/versions/node/v20.11.1/bin/node
    npm: 10.2.4 - ~/.nvm/versions/node/v20.11.1/bin/npm
    pnpm: 9.10.0 - /usr/bin/pnpm
  Browsers:
    Chrome: Not Found
  npmPackages:
    @emotion/react: ^11.11.4 => 11.13.3 
    @emotion/styled: ^11.11.5 => 11.13.0 
    @mui/base: ^5.0.0-beta.66 => 5.0.0-beta.66 
    @mui/core-downloads-tracker:  6.2.0 
    @mui/icons-material: ^6.2.0 => 6.2.0 
    @mui/lab: 6.0.0-beta.19 => 6.0.0-beta.19 
    @mui/material: ^6.2.0 => 6.2.0 
    @mui/private-theming:  6.2.0 
    @mui/styled-engine:  6.2.0 
    @mui/system: ^6.2.0 => 6.2.0 
    @mui/types:  7.2.19 
    @mui/utils:  6.2.0 
    @mui/x-data-grid: ^7.15.0 => 7.22.2 
    @mui/x-date-pickers:  7.22.2 
    @mui/x-internals:  7.21.0 
    @types/react: ^18.2.79 => 18.3.12 
    react: ^18.2.0 => 18.3.1 
    react-dom: ^18.3.0 => 18.3.1 
    styled-components: ^6.1.8 => 6.1.13 
    typescript: ^5.4.5 => 5.6.3 

Search keywords: autocomplete popper collapse transition

@IvanLuchkin IvanLuchkin added the status: waiting for maintainer These issues haven't been looked at yet by a maintainer label Dec 17, 2024
@IvanLuchkin
Copy link
Author

{
    name: 'trackPosition',
    enabled: true,
    phase: 'write',
    requires: ['computeStyles'],
    fn({
        state,
        instance
    }) {
        let previousY: number | null = null;
        let ticking = false;

        const observePosition = () => {
            const {
                reference
            } = state.elements;
            const currentY =
                reference.getBoundingClientRect().top;

            if (previousY !== currentY) {
                previousY = currentY;

                if (!ticking) {
                    ticking = true;
                    requestAnimationFrame(() => {
                        instance.update();
                        ticking = false;
                    });
                }
            }
        };

        observePosition();

        const resizeObserver = new ResizeObserver(
            observePosition,
        );
        resizeObserver.observe(
            state.elements.reference as Element,
        );
    },
},

Here is a popper.js modifier that fixes/mitigates the issue. Performance is a concern, though I have implemented it in an actual code and didn't notice perceivable issues

@mj12albert mj12albert added package: material-ui Specific to @mui/material component: autocomplete This is the name of the generic UI component, not the React module! labels Dec 18, 2024
@mnajdova
Copy link
Member

Thanks for linking the workaround. I think it would be a bad idea to add the resize observer by default, it could cause issues (likely perf too as you mentioned). I think I would just force re-render the select when a change like this happen instead of using resize observer (unless of course the change is not deterministic). I don't remember seeing different issue, let's see if it gets more upvotes before spending time on this.

@mnajdova mnajdova added this to the Material UI with Base UI milestone Dec 18, 2024
@mnajdova mnajdova removed the status: waiting for maintainer These issues haven't been looked at yet by a maintainer label Dec 18, 2024
@DiegoAndai DiegoAndai added the waiting for 👍 Waiting for upvotes label Dec 19, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
component: autocomplete This is the name of the generic UI component, not the React module! package: material-ui Specific to @mui/material waiting for 👍 Waiting for upvotes
Projects
None yet
Development

No branches or pull requests

4 participants