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] can't change option highlight color #19692

Closed
2 tasks done
jdoklovic opened this issue Feb 13, 2020 · 22 comments · Fixed by #26181
Closed
2 tasks done

[Autocomplete] can't change option highlight color #19692

jdoklovic opened this issue Feb 13, 2020 · 22 comments · Fixed by #26181
Labels
breaking change component: autocomplete This is the name of the generic UI component, not the React module! good first issue Great for first contributions. Enable to learn the contribution process.
Milestone

Comments

@jdoklovic
Copy link

  • The issue is present in the latest release.
  • 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

@oliviertassinari oliviertassinari added the component: autocomplete This is the name of the generic UI component, not the React module! label Feb 14, 2020
@oliviertassinari
Copy link
Member

@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 Implement theme level states design tokens #10870 (comment). The last iteration was on [Pagination] Second iteration #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.

@jdoklovic
Copy link
Author

@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!

@jdoklovic

This comment has been minimized.

@jdoklovic
Copy link
Author

jdoklovic commented Feb 14, 2020

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!

@oliviertassinari
Copy link
Member

oliviertassinari commented Feb 14, 2020

@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',
        },
      },
    },
  },
})

@oliviertassinari
Copy link
Member

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

@oliviertassinari oliviertassinari added the good first issue Great for first contributions. Enable to learn the contribution process. label Feb 22, 2020
@jeromeSH26
Copy link

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

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

@oliviertassinari
Copy link
Member

@jeromeSH26 See #19655.

@jeromeSH26
Copy link

@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

@rashdeva
Copy link

@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?

@oliviertassinari
Copy link
Member

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

@matthlavacka
Copy link

matthlavacka commented Apr 30, 2020

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,
   }}
/>

@sagar-gh
Copy link

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

@wald-tq
Copy link

wald-tq commented Sep 17, 2020

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
Copy link
Member

@wald-tq
Copy link

wald-tq commented Sep 17, 2020

@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 react-scripts@3.4.3.
See: https://stackoverflow.com/a/60464514/605586

I hope that we get a update soon.

@cchanche
Copy link

cchanche commented Dec 2, 2021

I see this issue has been closed, but i'm still not able to target a selected option with .Mui-selected. Only workaround is :

    MuiAutocomplete: {
      styleOverrides: {
        listbox: {
          '& .MuiAutocomplete-option[aria-selected="true"]': {  // works
            backgroundColor: 'lightBlue',
          },
          '& .MuiAutocomplete-option[aria-selected="true"].Mui-focused': { // works
            backgroundColor: 'blue',
          },
          '& .MuiAutocomplete-option.Mui-selected': { // doesn't works
            backgroundColor: 'lightRed',
          },
          '& .MuiAutocomplete-option.Mui-selected.Mui-focused': { // doesn't works
            backgroundColor: 'red',
          },
        },
      },
    },

I'd also like to point out that I can't get this working by directly using the option property :

    MuiAutocomplete: {
      styleOverrides: {
        option: { // <-- use option instead, not working
          '&[aria-selected="true"]': {
            backgroundColor: 'lightBlue',
          },
          '&[aria-selected="true"].Mui-focused': {
            backgroundColor: 'blue',
          },
          '&.Mui-selected': {
            backgroundColor: 'lightRed',
          },
          '&.Mui-selected.Mui-focused': {
            backgroundColor: 'red',
          },
        },
      },
    },

It looks like this second solution produces styles that get overwritten by the default styles from listbox :

image

I hope this can help. (using 5.2.2 and createTheme from @mui/material/styles)

@cchanche
Copy link

cchanche commented Dec 2, 2021

A bit unrelated, but I came in the styleOverrides to render a darker color than the default one, keeping my main theme. Turns out there is an opacity modifier for these types of colors within the theme.

image

It is a bit undocumented but it looks like it provides modifiers for all global state classes (like focus and active). I just modified the selectedOpacity and everything works fine.

@cchanche
Copy link

cchanche commented Dec 2, 2021

Sorry for spam, but after some more digging, it looks like the hover color is applied to a focused Mui-option, not the focusOpacity nor focus color. It looked a bit weird to me in the first place that it was called focused and hover does sounds better. Is this intended ?

Again sorry for the spamming, and thx for the amazing support 👍

@ayoub-root
Copy link

with MUI V5 it's working using

const useStyles = makeStyles({
option: {
"&.Mui-focused ": {
backgroundColor: green[100] + "!important",
},
},
});
..........

const styles = useStyles();
..........

<Autocomplete
classes={{
option: styles.option,
}}
.

@igortas
Copy link

igortas commented Jan 12, 2023

2023 and still not working.

@mokandev
Copy link

I was trying to find some solution to this problem, and I found this one:

  • I needed to import Paper from material-ui/core as I'm using material 4, and adds a custom style class to pass it to Paper component as it will be render inside of Autocomplete.
  • I passed the Paper component to Autocomplete component as the following code..
import { Autocomplete, Paper } from '@material-ui/core';
import { makeStyles } from '@material-ui/core/styles';

 

const useStyles = makeStyles(theme => ({
  customPaper: {
    backgroundColor: 'red', // Background Color that you want to use
    '& .MuiAutocomplete-option': {
      backgroundColor: 'blue' // Background Color that you want to use to options.
    }
  }
}));

 

function CustomAutocomplete() {
  const classes = useStyles();

  return (
<Autocomplete
      options={[{ title: 'Opção 1' }, { title: 'Opção 2' }, { title: 'Opção 3' }]}
      getOptionLabel={option => option.title}
      PaperComponent={props => (
<Paper {...props} className={classes.customPaper} />
      )}
      renderInput={params => <TextField {...params} label="Autocomplete" variant="outlined" />}
    />
  );
}

I hope this can help someone else. =)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
breaking change component: autocomplete This is the name of the generic UI component, not the React module! good first issue Great for first contributions. Enable to learn the contribution process.
Projects
None yet