Material-ui: [Autocomplete] can't change option highlight color

Created on 13 Feb 2020  路  16Comments  路  Source: mui-org/material-ui

  • [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 馃槸

The Autocomplete component uses a very light default option highlight and doesn't exposes any CSS props to easily change it as far as i can tell.

Expected Behavior 馃

an easy css classname/selector exposed to change the highlight color of the options

currently, it's setting .MuiAutocomplete-option[data-focus="true"] but I can't figure out how to actually change that using makeStyles or any other documented way

breaking change Autocomplete good first issue

Most helpful comment

Actually, I found a solution that will work for now.
I just needed to do:

const useStyles = makeStyles({
    '@global': {
        '.MuiAutocomplete-option[data-focus="true"]': {
            background: 'blue'
        }
    }

});

and then in my component function, simply call
useStyles();

It's not great, but it will get me through until a "real" solution is found.

Thanks!

All 16 comments

@jdoklovic Thanks for opening this issue. This raises interesting underlying concerns. I see a couple of dimensions to it.

  1. attribute. I'm not aware of any cases, across all our components, where we use data- attributes to solve this problem. Maybe I was too influenced when benchmarking Reach UI. So, in this case, I would propose that we stick to the patter we use elsewhere: .Mui-disabled and .Mui-selected class names. This would be a breaking change.
  2. UI. This lab component is a great opportunity to continue the experiment on https://github.com/mui-org/material-ui/issues/10870#issuecomment-575609444. The last iteration was on #19612.

Regarding your very issue, there is nothing specific, pick whatever styling solution you use in your app, use the correct CSS selector, make sure you have more CSS specificity, you are good.

@oliviertassinari Thanks for the info. By chance do you know what I could put in makeStyles from MUI to target the attribute selector? I haven't had any luck doing it and I currently don't have any stylesheets and want to avoid adding one just for this.

I should also note that this is going to be used in a themeable host where we use a "dynamic" MUI theme that adjusts it's colors and typography based on the host theme, so it would be nice to be able to target this selector in a theme.

Thanks again!

just for clarity, I've tried hacking it using this code:

const useStyles = makeStyles({
    'option[data-focus="true"]': {
        background: 'blue'
    }
}, { name: 'MuiAutocomplete' });

I can see that it does indeed generate the proper classname, however, the component complains that it doesn't accept the key:

image

Actually, I found a solution that will work for now.
I just needed to do:

const useStyles = makeStyles({
    '@global': {
        '.MuiAutocomplete-option[data-focus="true"]': {
            background: 'blue'
        }
    }

});

and then in my component function, simply call
useStyles();

It's not great, but it will get me through until a "real" solution is found.

Thanks!

@jdoklovic This is, from my perspective a "support request"

I should also note that this is going to be used in a themeable host where we use a "dynamic" MUI theme that adjusts it's colors and typography based on the host theme, so it would be nice to be able to target this selector in a theme.

You could use the theme directly, but global styles (like you did) works great too!

createMuiTheme({
  overrides: {
    MuiAutocomplete: {
      option: {
        '&[data-focus="true"]': {
          backgroundColor: 'red',
        },
      },
    },
  },
})

Regarding the normalization of the API, I have the following diff in mind:

diff --git a/packages/material-ui-lab/src/Autocomplete/Autocomplete.js b/packages/material-ui-lab/src/Autocomplete/Autocomplete.js
index 463ff0f2f..b6405c638 100644
--- a/packages/material-ui-lab/src/Autocomplete/Autocomplete.js
+++ b/packages/material-ui-lab/src/Autocomplete/Autocomplete.js
@@ -204,7 +204,7 @@ export const styles = theme => ({
     '&[aria-selected="true"]': {
       backgroundColor: theme.palette.action.selected,
     },
-    '&[data-focus="true"]': {
+    '&.Mui-focused': {
       backgroundColor: theme.palette.action.hover,
     },
     '&:active': {
diff --git a/packages/material-ui-lab/src/Autocomplete/Autocomplete.test.js b/packages/material-ui-lab/src/Autocomplete/Autocomplete.test.js
index bf6f017c9..482f4dace 100644
--- a/packages/material-ui-lab/src/Autocomplete/Autocomplete.test.js
+++ b/packages/material-ui-lab/src/Autocomplete/Autocomplete.test.js
@@ -67,7 +67,7 @@ describe('<Autocomplete />', () => {
       );

       function checkHighlightIs(expected) {
-        expect(getByRole('listbox').querySelector('li[data-focus]')).to.have.text(expected);
+        expect(getByRole('listbox').querySelector('li.Mui-focused')).to.have.text(expected);
       }

       checkHighlightIs('one');
@@ -782,7 +782,7 @@ describe('<Autocomplete />', () => {
       fireEvent.keyDown(document.activeElement, { key: 'ArrowDown' }); // goes to 'two'

       function checkHighlightIs(expected) {
-        expect(listbox.querySelector('li[data-focus]')).to.have.text(expected);
+        expect(listbox.querySelector('li.Mui-focused')).to.have.text(expected);
       }

       checkHighlightIs('two');
diff --git a/packages/material-ui-lab/src/useAutocomplete/useAutocomplete.js b/packages/material-ui-lab/src/useAutocomplete/useAutocomplete.js
index 3c01bb4b3..edf689f65 100644
--- a/packages/material-ui-lab/src/useAutocomplete/useAutocomplete.js
+++ b/packages/material-ui-lab/src/useAutocomplete/useAutocomplete.js
@@ -146,9 +146,9 @@ export default function useAutocomplete(props) {
       return;
     }

-    const prev = listboxRef.current.querySelector('[data-focus]');
+    const prev = listboxRef.current.querySelector('.Mui-focused');
     if (prev) {
-      prev.removeAttribute('data-focus');
+      prev.classList.remove('Mui-focused');
     }

     const listboxNode = listboxRef.current.parentElement.querySelector('[role="listbox"]');
@@ -169,7 +169,7 @@ export default function useAutocomplete(props) {
       return;
     }

-    option.setAttribute('data-focus', 'true');
+    option.classList.add('Mui-focused');

     // Scroll active descendant into view.
     // Logic copied from https://www.w3.org/TR/wai-aria-practices/examples/listbox/js/listbox.js
createMuiTheme({
  overrides: {
    MuiAutocomplete: {
      option: {
        '&[data-focus="true"]': {
          backgroundColor: 'red',
        },
      },
    },
  },
})

FYI
typescript is complaining because all MUIAutoComplete classes are not in ThemeOptions object.

@jeromeSH26 See #19655.

@oliviertassinari merci Olivier, but I already had a look at the official answer ;-)
Of course extending the default theme is a solution (that I have partialy applied BTW) but this is not very dry and quite annoying as you mostly need to recreate/reimporte all the types related to the classes already done by the lab. ;-)

Would you mind having a look at #19827 ? This is also an annoying situation I'm facing and can't fixed.

Rgds

@oliviertassinari there is another problem with hover color.
When you select items by keyboard, the hover state in Select is palette.action.selected, but for Autocomplete is palette.action.hover.

Could we bring them to one view?

@rash2x We need to revamp the state styles, see #5186.

I'm able to change it by doing:

createStyles({
    listbox: {
      padding: 0,
    },
    option: {
      borderBottom: `1px solid ${theme.palette.system[5]}`,
      // Hover
      '&[data-focus="true"]': {
        backgroundColor: theme.palette.secondSurface.light,
        borderColor: 'transparent',
      },
      // Selected
      '&[aria-selected="true"]': {
        backgroundColor: theme.palette.secondSurface.main,
        borderColor: 'transparent',
      },
    },
  });

<Autocomplete
   classes={{
      option: cs.option,
      listbox: cs.listbox,
   }}
/>

@matthlavacka Thank you,i can change any props with this

To fix the TypeScript error I added the MuiAutocomplete with AutocompleteClassKey to the ComponentNameToClassKey which is used in the Overrides Interface to declare the keys and properties.

import { AutocompleteClassKey } from '@material-ui/lab/Autocomplete';

declare module '@material-ui/core/styles/overrides' {
  interface ComponentNameToClassKey {
    MuiAutocomplete: AutocompleteClassKey
  }
}

@oliviertassinari thanks a lot!
I also found also this in the changelog: https://github.com/mui-org/material-ui/blob/next/CHANGELOG.md#4102
Guess we are updating from 4.9.11 to 4.10.2

After updating the packages and trying to use the described method:

import type '@material-ui/lab/themeAugmentation';

I figured out, that it won't compile when using the latest [email protected].
See: https://stackoverflow.com/a/60464514/605586

I hope that we get a update soon.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

zabojad picture zabojad  路  3Comments

ghost picture ghost  路  3Comments

sys13 picture sys13  路  3Comments

ryanflorence picture ryanflorence  路  3Comments

iamzhouyi picture iamzhouyi  路  3Comments