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

[Autocomplete] Composing `endAdornment` overlaps collapse/expand icon

Open yhunko opened this issue 4 years ago • 17 comments

See https://github.com/mui-org/material-ui/issues/28465#issuecomment-927613778 for general problem description.

  • [x] The issue is present in the latest release.
  • [x] I have searched the issues of this repository and believe that this is not a duplicate.

Current Behavior 😯

endAdornment overlaps with the loading indicator.

Screenshot from 2021-09-19 10-11-36

Example code:

    renderInput={(params) => {
      return (
        <TextField
          // eslint-disable-next-line react/jsx-props-no-spreading
          {...params}
          label={'Select service providers'}
          InputProps={{
            ...params.InputProps,
            endAdornment: (
              <React.Fragment>
                <CircularProgress color={'inherit'} size={20} />
                {params.InputProps.endAdornment}
              </React.Fragment>
            ),
          }}
        />
      )
    }}

Expected Behavior 🤔

Loading indicator should be positioned next to the endAdornment as it was in v4

Steps to Reproduce 🕹

Frozen CodeSandbox: https://codesandbox.io/s/autocomplete-composed-endadornment-vemqi

Steps:

  1. Migrate from v4 to v5 using safe codemod
  2. Setup async Autocomplete component as described here: https://mui.com/components/autocomplete/#asynchronous-requests

Context 🔦

Not really sure what to write here... Well, the code above worked perfectly in v4 but now it seems to be broken for me...

Your Environment 🌎

`npx @mui/envinfo`
  System:
    OS: Linux 5.11 Linux Mint 20.2 (Uma)
  Binaries:
    Node: 14.17.5 - ~/.nvm/versions/node/v14.17.5/bin/node
    Yarn: 1.22.11 - ~/.nvm/versions/node/v14.17.5/bin/yarn
    npm: 7.20.6 - ~/.nvm/versions/node/v14.17.5/bin/npm
  Browsers:
    Chrome: 93.0.4577.82
  npmPackages:
    @emotion/react: ^11.4.1 => 11.4.1 
    @emotion/styled: ^11.3.0 => 11.3.0 
    @mui/core:  5.0.0-alpha.47 
    @mui/icons-material: ^5.0.0 => 5.0.0 
    @mui/lab: ^5.0.0-alpha.47 => 5.0.0-alpha.47 
    @mui/material: ^5.0.0 => 5.0.0 
    @mui/private-theming:  5.0.0 
    @mui/styled-engine:  5.0.0 
    @mui/styled-engine-sc: ^5.0.0 => 5.0.0 
    @mui/styles: ^5.0.0 => 5.0.0 
    @mui/system:  5.0.0 
    @mui/types:  7.0.0 
    @mui/utils:  5.0.0 
    @types/react: ^17.0.21 => 17.0.21 
    react: ^17.0.2 => 17.0.2 
    react-dom: ^17.0.2 => 17.0.2 
    styled-components: ^5.3.1 => 5.3.1 
    typescript: ^4.4.2 => 4.4.3

yhunko avatar Sep 19 '21 07:09 yhunko

It positions itself as expected when the close icon is present (it appears when at least one item is selected, which is also an expected behavior).

But when there are no items checked - it overlaps with endAdornment again.

Screenshot from 2021-09-19 10-26-28

yhunko avatar Sep 19 '21 07:09 yhunko

The code you posted is not the same as the one you linked. Following our example, fixes the issue:

    renderInput={(params) => {
      return (
        <TextField
          // eslint-disable-next-line react/jsx-props-no-spreading
          {...params}
          label={'Select service providers'}
          InputProps={{
            ...params.InputProps,
            endAdornment: (
              <React.Fragment>
-               <CircularProgress color={'inherit'} size={20} />
+               {loading ? <CircularProgress color="inherit" size={20} /> : null}
                {params.InputProps.endAdornment}
              </React.Fragment>
            ),
          }}
        />
      )
    }}

eps1lon avatar Sep 19 '21 09:09 eps1lon

@eps1lon are you sure that it fixes the issue?

The issue is not when the loading indicator is being displayed but rather how. I removed conditional rendering for loading indicator to be always visible for demo purposes.

The issue is still there with this code:

      renderInput={(params) => {
        return (
          <TextField
            // eslint-disable-next-line react/jsx-props-no-spreading
            {...params}
            label={'Select service providers'}
            InputProps={{
              ...params.InputProps,
              endAdornment: (
                <React.Fragment>
                  {loading ? (
                    <CircularProgress color={'inherit'} size={20} />
                  ) : null}
                  {params.InputProps.endAdornment}
                </React.Fragment>
              ),
            }}
          />
        )
      }}

Here you can take another example, which worked without a problem before migration:

      renderInput={(params) => {
        const textFieldProps: TextFieldProps = {
          label: 'Job Titles',
          variant: 'outlined',
          placeholder: 'Start typing to filter the results...',
          InputProps: {
            ...params.InputProps,
            ...{
              endAdornment: (
                <>
                  {loading ? (
                    <CircularProgress color={'inherit'} size={20} />
                  ) : (
                    <Tooltip title={'Select All'}>
                      <IconButton size={'small'} onClick={handleSelectAll}>
                        <SelectAll />
                      </IconButton>
                    </Tooltip>
                  )}
                  {params.InputProps.endAdornment}
                </>
              ),
            },
          },
        }
        return React.createElement(TextField, { ...params, ...textFieldProps })
      }}

Screenshot from 2021-09-19 13-00-13

And it is positioned as expected with the close button.

Screenshot from 2021-09-19 13-00-26

yhunko avatar Sep 19 '21 10:09 yhunko

Please consider re-opening this @eps1lon. We are having the same issue with the following code:

      renderInput={(params) => {
        return (
          <TextField
            {...params}
            size="small"
            name={name || ''}
            label={label}
            placeholder={placeholder}
            helperText={helperText}
            error={error}
            required={required}
            InputProps={{
              ...params.InputProps,
              endAdornment: (
                <>
                  {loading ? <CircularProgress color="inherit" size={20} /> : null}
                  {params.InputProps.endAdornment}
                </>
              ),
            }}
          />
        );
      }}

digging a bit and comparing with the example in the docs, it appears this is only an issue when using size="small" (removing this prop results in the loader being positioned correctly) because size="small" is removing the padding-right required to align the spinner properly (or any other endAdornment for that matter)

with size="small" image

without image

corbenf-shuttlerock avatar Sep 19 '21 19:09 corbenf-shuttlerock

It doesn't look like this bug report has enough info for one of us to reproduce it.

Please provide a CodeSandbox (https://material-ui.com/r/issue-template-latest).

Here are some tips for providing a minimal example: https://stackoverflow.com/help/mcve

eps1lon avatar Sep 20 '21 09:09 eps1lon

@eps1lon reproduced it without a problem in this Sandbox: https://codesandbox.io/s/elastic-haze-tmmmo?file=/src/Demo.tsx

I can't understand why there is not enough info to reproduce it...

It happens with Autocomplete size prop being set to 'small', as @corbenf-shuttlerock said.

yhunko avatar Sep 20 '21 12:09 yhunko

I can't understand why there is not enough info to reproduce it...

There was no full codesandbox. Just snippets of code. We don't try to patch them up because it takes up a considerable amount of our time and might not resemble the original issue.

Now that we have codesandbox.io/s/elastic-haze-tmmmo?file=/src/Demo.tsx, that's another issue.

But that's unrelated to loading indicators. How to make them work is already described in the documentation you linked. The problem is common for all composed endAdornment: https://codesandbox.io/s/autocomplete-composed-endadornment-vemqi

eps1lon avatar Sep 27 '21 07:09 eps1lon

I ran into the same issue. Using Autocomplete component with size='small' overlaps endAdornment & expand icon.

As I understand, it is because Autocomplete use an InputBase component with a padding set to 6px if size='small' :

Capture d’écran 2021-10-13 à 14 45 22

In my opinion, the proper way to deal with that, is to override your Autocomplete styles via your theme configuration. Something like :

// under theme.components

MuiAutocomplete: {
    styleOverrides: {
        root: {
            '.MuiOutlinedInput-root.MuiInputBase-sizeSmall': {
                padding: '39px',
                // or padding: theme.spacing(X) if you want to be more precise & already defined your theme
            },
        },
    },
},

Each Autocomplete with size='small' will now be rendered with a 39px padding preventing overlaps.

Hope this helps you.

DeLm0re avatar Oct 13 '21 12:10 DeLm0re

Ran into the same issue with the prop size="small" given to <Autocomplete />.

@DeLm0re's code does fix the issue.

efournival avatar Mar 09 '22 14:03 efournival

Some css to fix it

.MuiAutocomplete-root .MuiOutlinedInput-root.MuiInputBase-sizeSmall {
    padding-right: 39px;
}
.MuiAutocomplete-root.MuiAutocomplete-hasClearIcon .MuiOutlinedInput-root.MuiInputBase-sizeSmall {
    padding-right: 65px;
}

wong1993 avatar Jun 02 '22 04:06 wong1993

My Autocomplete dropdown list depends on database query results from my textfield input. I found Autocomplete's freeSolo field was a better solution for me, rather than Autocomplete's default to assume a static dropdown list with a ArrowDropDownIcon. Using Autocomplete's freeSolo field removes the ArrowDropDownIcon from my textfield and is the better solution for in my case.

ethan-davis-seekout avatar Jun 02 '22 16:06 ethan-davis-seekout

@DeLm0re would you like to create a PR for the proposed changes? We can use the screenshot tests to verify that this works in all scenarios.

mnajdova avatar Sep 28 '22 06:09 mnajdova

@mnajdova Of course, I look into it when I have time.

I am a just a bit confuse with this comment :

// In Autocomplete.js

[`& .${outlinedInputClasses.root}.${inputBaseClasses.sizeSmall}`]: {
    // Don't specify paddingRight, as it overrides the default value set when there is only
    // one of the popup or clear icon as the specificity is equal so the latter one wins
    paddingTop: 6,
    paddingBottom: 6,
    paddingLeft: 6,
    [`& .${autocompleteClasses.input}`]: {
      padding: '2.5px 4px 2.5px 6px',
    },
},

Looks like this piece of code was written when .MuiAutocomplete-hasClearIcon (autocompleteClasses.hasClearIcon) was not a thing yet.

I can re-write it to patch this issue however.

DeLm0re avatar Sep 28 '22 11:09 DeLm0re

Same issue here!

image

Adding

sx={{
    '& .MuiInputBase-root': {
        paddingRight: '39px !important'
    }
}}

to the autocomplete component fixed it.

iMrDJAi avatar Oct 04 '22 17:10 iMrDJAi

If someone has time to create a PR with the fix I would be happy to review it. It's hard to say if any of these is the correct fix to the solution without checking if there are no visual regressions in other scenarios.

mnajdova avatar Oct 14 '22 09:10 mnajdova

Issue seems to be resolved, as of @mui/[email protected].

elawad avatar Dec 29 '23 18:12 elawad

Issue seems to be resolved, as of @mui/[email protected].

Still happening in version 6

TiagoPortfolio avatar Sep 12 '24 15:09 TiagoPortfolio