travis_moulton
travis_moulton

Reputation: 143

MaterialUI v5 -> How to style Autocomplete options

I'm trying to apply some basic styles to the options inside the Autocomplete component from MUI v5. I'm just trying to change the background color on hover, and based on whether or not it is selected. I've tried 2 approaches based on the documentation, using a theme, and applying the sx prop to Autocomplete.

Using Theme almost has me there, code below:

import { createTheme, ThemeProvider } from '@mui/material/styles';

const theme = createTheme({
  components: {
    MuiAutocomplete: {
      styleOverrides: {
        option: {
          '&[aria-selected="true"]': {
            backgroundColor: '#e3abed',
          },

          '&:hover': {
            backgroundColor: '#9c27b0',
          },
          backgroundColor: '#fff',
        },
      },
    },
  },
})

I have the ThemeProvider wrapped around my entire app

and the component:

<Autocomplete
  options={['1', '2', '3']}
  renderInput={(params) => <TextField {...params} label="Priority" />}
  onChange={(_e, val) => setPriority(val)}
/>

So, this almost works. However the [aria-selected="true"] styling is only being applied when I am also hovering over another option in the dropdown. Otherwise it's the default grey that comes with the component and I don't understand why.

The second path I have tried is to use the sx prop on the Autocomplete component. In the docs it says you can target child components by their class name: https://mui.com/material-ui/customization/how-to-customize/#overriding-styles-with-class-names

Here is my component:

<Autocomplete
  options={['1', '2', '3']}
  renderInput={(params) => <TextField {...params} label="Priority" />}
  onChange={(_e, val) => setPriority(val)}
  sx={{
    '& .MuiAutocomplete-option': {
      backgroundColor: '#000',
    },
    '& .Mui-focused': {
      backgroundColor: 'red',
    },
  }}
  open
/>

That doesn't appear to be having any effect. I've been working on this for almost 2 hours and can't seem to get to the finish line here. Any help would be greatly appreciated.

Upvotes: 8

Views: 24306

Answers (6)

vmakinen
vmakinen

Reputation: 91

If you just need custom styling CustomPaper component might be an overkill (and I also faced some TypeScript issues trying that).

For simple styling you can use slotProps:

<Autocomplete
  slotProps={{
    paper: {
      sx: {
        '& .MuiAutocomplete-listbox': {
          '& .MuiAutocomplete-option': {
            display: 'flex',
            flexDirection: 'column',
            alignItems: 'flex-start',
          },
        },
      },
    },
  }}
  ... 

/>

Upvotes: 6

Areeb111
Areeb111

Reputation: 65

You can override the style of Autocomplete list items by using the makeStyle() in your functional component with these attributes:

'@global': {
    '& .MuiAutocomplete-popper': {
        '& .MuiPaper-root': {
            '& .MuiAutocomplete-listbox': {
                '& li': {
                    fontSize: '14px !important',
                    paddingTop: 0,
                    paddingBottom: 0
                }
            }
        }
    },
  },

Because it's being created in the root element of DOM.

Upvotes: 1

jumbers
jumbers

Reputation: 91

function CustomPaper({ children }) {
  return (
    <Paper 
      sx={{
        "& .MuiAutocomplete-listbox": {
          "& .MuiAutocomplete-option[aria-selected='true']": {
            bgcolor: "purple",
            "&.Mui-focused": {
              bgcolor: "purple",
            }
          }
        },
        "& .MuiAutocomplete-listbox .MuiAutocomplete-option.Mui-focused": {
          bgcolor: "red",
        }
      }}
    >
      {children}
    </Paper>
  );
}

Following up on Lars' answer, here's an example using a custom Paper component. Just pass in the custom Paper component name to the PaperComponent prop on Autocomplete <Autocomplete PaperComponent={CustomPaper} {...blahBlahOtherProps} />. This way is nice if you don't want to override the theme for all Autocomplete components.

Upvotes: 5

Lokkesh
Lokkesh

Reputation: 154

I too faced this issue and found a solution. You Can try this to set the css for options, single option and while hovered (focused) in the Autocomplete using 'sx' prop

Easy Way to customize your AutoComplete component which can be used in Mui V5

  <Autocomplete
  limitTags={1}
  disablePortal
  id="simple-search"
  value={select.region}
  onChange={handleChange("region")}
  options={region}
  sx={{
  width: { sm: "100%", md: 340 },
  "& + .MuiAutocomplete-popper .MuiAutocomplete-option": 
      {
        backgroundColor: "#363636",
      },
  "& + .MuiAutocomplete-popper .MuiAutocomplete-option[aria-selected='true']":
      {
        backgroundColor: "#4396e6",
      },
  "& + .MuiAutocomplete-popper .MuiAutocomplete-option[aria-selected ='true'] .Mui-focused":
      {
        backgroundColor: "#3878b4",
      },
    }}
 disableCloseOnSelect
 multiple
 renderInput={(params) => (
      <TextField {...params} label="Region" color="info" />
     )}
  />

Upvotes: 1

Lars Kemmann
Lars Kemmann

Reputation: 5674

I had the same problem; turns out I just needed to explore the Autocomplete API docs' Props section a bit further. There are several customization possibilities if you don't want to deal with global theme customization:

  1. The PaperComponent prop allows customization of "[t]he component used to render the body of the popup." Note that simply using sx on Autocomplete does not work here because (as @bnays-mhz pointed out) the PopperComponent that the PaperComponent is nested in lives outside the main DOM tree (for z-index/modal UX purposes).
  2. The renderGroup prop allows overriding the rendering of option group headers.
  3. The renderOption prop allows overriding the rendering of individual options.

Upvotes: 4

bnays mhz
bnays mhz

Reputation: 503

You can override Autocomplete options css by targeting class

'.MuiAutocomplete-popper'

You will have to apply css globally because this node is created outside the root element in DOM.

Upvotes: 1

Related Questions