mui / material-ui

Material UI: Comprehensive React component library that implements Google's Material Design. Free forever.
https://mui.com/material-ui/
MIT License
93.86k stars 32.26k forks source link

MuiFormLabel Focused color problem #11244

Closed luiscdz closed 6 years ago

luiscdz commented 6 years ago

Expected Behavior

When I create a new theme and override focused prop of MuiFormLabel, MaterialUI not used this new class because it create high new class that override my new class.

Current Behavior

Steps to Reproduce (for bugs)

  1. Create a new theme and override MuiFormLabel on color 'focused' prop https://material-ui.com/api/form-label/#css-api
  2. Create a component with a Texfield
  3. Apply new theme on your app

https://codesandbox.io/s/52poq578vn

Context

I need to change color label when the input is focus, in beta 41 it is work.

Your Environment

Tech Version
Material-UI beta 43+
React 16.3.2
browser Chrome, Firefox
oliviertassinari commented 6 years ago

@luiscdz We have recently documented the specificity change introduced: #11227. It applies to the overrides key too. You have two alternatives:

import React from "react";
import { TextField, createMuiTheme, ThemeProvider } from "@material-ui/core";

const theme = createMuiTheme({
  overrides: {
    MuiInputLabel: { // Name of the component ⚛️ / style sheet
      root: { // Name of the rule
        color: "orange",
        "&$focused": { // increase the specificity for the pseudo class
          color: "blue"
        }
      }
    }
  }
});

function OverridesCss() {
  return (
    <ThemeProvider theme={theme}>
      <TextField value="value" label="label" />
    </ThemeProvider>
  );
}

export default OverridesCss;

https://codesandbox.io/s/q31w90krn9

Capture d’écran 2019-04-04 à 10 35 12 Capture d’écran 2019-04-04 à 10 35 16

marsonmao commented 6 years ago

Can I use local override to do the same thing? I've tried the below setup but it gives me this warning: Warning: [JSS] Could not find the referenced rule focused in D8TextField.

Codes here:

const styles = (theme) => {
  return {
    formLabelRoot: {
      '&$focused': { color: 'green' }, // not working
      // color: 'cyan', // this is working
    },
    formLabelFocused: {
      '&$focused': { color: 'pink' }, // not working
      color: 'blue', // not working
    },
  };
};

class D8TextField extends React.Component {
  render() {
    return (
      <TextField
        // ...omitting some props
        InputLabelProps={{
          shrink: true,
          FormLabelClasses: {
            root: classes.formLabelRoot,
            focused: classes.formLabelFocused,
          },
        }}
      />
    );
  }
}

Mui version is 1.0.0-beta.45. By the way, the focused class provided here is applied to the form label (I mean the color: 'blue'), but the color property is still overided by the mui original one. Please check the attached image. formlabel

oliviertassinari commented 6 years ago

Can I use local override to do the same thing?

@marsonmao Yes, you can. formLabelFocused -> focused.

marsonmao commented 6 years ago

@oliviertassinari Ohh got it! Finally I realized the rule, thanks! But I modified the key name to make it easier to write the style:

    formLabelRoot: { // must provide all of formLabelRoot && '&$formLabelFocused' && formLabelFocused
      '&$formLabelFocused': { color: theme.palette.primary.main },
    },
    formLabelFocused: {
      // color: 'green', // won't affect anything
    },

    <TextField
      InputLabelProps={{
        FormLabelClasses: {
          root: classes.formLabelRoot,
          focused: classes.formLabelFocused,
        },
      }}
    />

By the way...I found this part of FormLabel kina weird:

    '&$focused': {
      color: theme.palette.primary[theme.palette.type === 'light' ? 'dark' : 'light'],
    },

Is it a typo? (I mean should it be 'light' : 'dark'?)

oliviertassinari commented 6 years ago

@marsonmao I'm happy you have found a solution. No, it's not a typo. Does the specification ask for something else?

marsonmao commented 6 years ago

@oliviertassinari Ok then it's fine. I was just wondering if the light type should match the light theme, if it's the opposite then it's an intentionally made art decision.

jstgermain commented 6 years ago

@luiscdz We have recently documented the specificity change introduced: #11227. It applies to the overrides key too. You have two alternatives:

  overrides: {
    MuiFormLabel: {
      root: {
        color: "orange",
        "&$focused": {
          color: "red"
        }
      },
      focused: {
        "&$focused": {
          color: "yellow"
        }
      }
    }
  }

the only part that I didn't try before googling... thanks.

RyRy79261 commented 5 years ago

Is there any reason why the focused class doesn't apply styling to focused elements without stating the element with the class currently set as focused, being in focus?

Seems pointlessly redundant, why have a focused class at all and just add the internal state to the original control

oliviertassinari commented 5 years ago

@RyRy79261 We handle the focus class like a pseudo class (:focused, :hover, etc.) you have to increase specificity so you can scope the override to a specific state without messing the default one.

RyRy79261 commented 5 years ago

@oliviertassinari Thanks for the reply, but I'm failing to understand why the focused class would be assigned to an element that isnt in a focused state thus requiring being that specific.

I'm also struggling to see the scoping issue as applying styles to the root element made no difference, only an element with the class focus, that is also explicitly in focus had the css applied to it.

Is there a situation where an form element has the focus class applied to its label by the default behaviour of focusing on an input without said form element actually being in a state of focused?

oliviertassinari commented 5 years ago

I don't understand what you don't understand. The focused class is only applied when the input is focused. If the focused styles color had a specificity of one, it would be overriden when you change the non focused color. The prevent this problem, it has a specificity of two. The CSS specification used the same logic to define the pseudo classes specificity impact.

RyRy79261 commented 5 years ago

As an example

There's a label, when the label's input is in focus, the class name focused is added.

If you then unfocus, this class is removed, implying that the focused class is removed, thus the styling defined by the class titled focused should only be applied when the input is focused.

However, the definition here states, that even though that class, called focused, is only applied when that is the state, you then need to specify that the focused element is explicitly in a focused state.

logically:

.focused{
   // Focused styles
}

Actual:

.focused{
   "&$focused":{
       // styles
    }
}

This means that either specifying the state of focused, in a focus class is redundant, or having the focus class to apply in that state is redundant

oliviertassinari commented 5 years ago

Actual:

@RyRy79261 That's not how it should be done. It's should be something like this (in equivalent CSS #15140):

.mui-input-label.focused {
  color: red;
}

I have updated my misleading comment, sorry.

RyRy79261 commented 5 years ago

@oliviertassinari

Thank you, however my issue is that the code you added there does not render.


.focused{
   "&$focused":{
       // styles
    }
}```

Only when I do it like that does it work
oliviertassinari commented 5 years ago

@RyRy79261 Check this comment: https://github.com/mui-org/material-ui/issues/11244#issuecomment-386792253.

jonasms commented 5 years ago
overrides: {
      MuiButton: {
        root: {
          "&$focused": {
            border: "2px solid #337DFD"
          }
        },

is not working for me. I can't find the styles in Chrome debugger at all, I don't think it's a case of them being overrided by more specific styles.

Help?

oliviertassinari commented 5 years ago

@JonasMS Make sure your custom theme is correctly applied.

gschema commented 4 years ago

Just to add a bit of insight here which might be useful for some.

Some of the component might allow for things like this:

// somewhere in the proj
const primaryColor = '#bada55';
const errorColor = '#ba0000';

// theme override:
// ...
MuiInputLabel: {
      root: {
        "&$shrink": {
          color: grey[900],
          "&$focused": {
            color: primaryColor,
          }
        },

        "&$error": {
          color: errorColor,

          "&$focused": {
            // notice this nesting; perfectly legal and overrides default specificity on theme level
            "&$shrink": {
              color: darker(errorColor, 0.5),
            }
          }
        }
      }
    },
// ....

Hope this might help someone.

ghost commented 3 years ago

This is hell 🙃

abdeldjalilhachimi commented 2 years ago

I have fixed this issue by adding global css file and I put there this label { color : green // you can put your primary color based on costumized theme }

MyJooeee commented 2 years ago

To custom focused label on TextField locally :

import { makeStyles } from '@mui/styles';

...

const useStyles = makeStyles((theme) => ({
    root: {
      '& label.Mui-focused': {
        color: theme.palette.error.main
      }
    }
  }));

const classes = useStyles();

<TextField
    className={classes.root}
    ...
 />

Hope it helps ;)

vitaly-ivanov-navidium commented 2 years ago

mui 5 example

import { formLabelClasses } from "@mui/material";
import { createTheme } from "@mui/material/styles";
import { grey } from "@mui/material/colors";

export const theme = createTheme({
    components: {
        MuiFormLabel: {
            styleOverrides: {
                root: {
                    color: grey[400],
                    [`&.${formLabelClasses.focused}`]: { 
                        color: grey[800]
                    }
                }
            }
        }
    }
})
JahnoelRondon commented 1 year ago

lord have mercy trying to use mui theme and overriding with a css file is a catastrophe and just breaks the css.

JahnoelRondon commented 1 year ago

@vitaly-ivanov-navidium c You need to make sure that its wrapped in component, also missing a bracket at the beginning of formlabelclass string. also I wonder why focused doesnt change the color of it if its in the api?

  components: {
    MuiInputLabel: {
      styleOverrides: {
        root: {
          color: "white",
        },
       focused: {
         color: "purple",
       },
      },
    },
  },
vitaly-ivanov-navidium commented 1 year ago

thanks @JahnoelRondon, I corrected the code to look accurate. Regarding your question - that was just part of our design to retain label color even on focus (updated as well to avoid confusion).

kdevay commented 4 months ago

Hello, @oliviertassinari, and any other MUI experts,

I need some help! I have a highly customized text field which requires overrides for basically every concievable state 😅 . I was able to get every customization to work properly by adding the following overrides to the theme:

MuiTextField: {
      styleOverrides: {
        root: {
          display: 'flex',
          padding: 0,
          alignItems: 'flex-start',
          gap: '10px',
          alignSelf: 'stretch',
          backgroundColor: '#F1F1F1 !important',
          borderRadius: '120px',
          color: '#3D3D3D',
        },
      },
    },
    MuiOutlinedInput: {
      styleOverrides: {
        root: {
          display: 'flex',
          alignItems: 'flex-start',
          gap: '10px',
          alignSelf: 'stretch',
          backgroundColor: '#F1F1F1 !important',
          borderRadius: '120px',
          padding: 0,
          color: '#3D3D3D',
          '& .MuiInputBase-root': {
            backgroundColor: '#F1F1F1 !important',
            padding: '10px 16px', // Adjust padding for input field
          },
          '& .MuiOutlinedInput-input': {
            backgroundColor: '#F1F1F1 !important',
            borderRadius: '120px',
            padding: '10px 16px',
          },
          '& .MuiInputBase-input': {
            padding: '10px 16px',
          },
          '&:hover .MuiOutlinedInput-notchedOutline': {
            borderColor: '#E5E7EB',
          },
          '& .MuiOutlinedInput-input:focus': {
            backgroundColor: 'transparent',
          },
          '&.Mui-focused .MuiOutlinedInput-notchedOutline': {
            borderColor: '#3D3D3D',
          },
          '&.Mui-disabled .MuiOutlinedInput-notchedOutline': {
            borderColor: '#F5F5F7',
          },
          '&.Mui-disabled:hover .MuiOutlinedInput-notchedOutline': {
            borderColor: '#F5F5F7',
          },
          '&.Mui-active .MuiOutlinedInput-notchedOutline': {
            borderColor: '#F1F1F1!important',
          },
          '&.Mui-error .MuiOutlinedInput-notchedOutline': {
            borderColor: '#E01E5A',
            boxShadow: '0px 0px 0px 2px #FEAEB6',
          },
          '&.Mui-error:hover .MuiOutlinedInput-notchedOutline': {
            borderColor: '#E01E5A',
            boxShadow: '0px 0px 0px 2px #FEAEB6',
          },
          '&.Mui-error.Mui-focused .MuiOutlinedInput-notchedOutline': {
            borderColor: '#E01E5A',
            boxShadow: '0px 0px 0px 2px #FEAEB6',
          },
        },
        notchedOutline: {
          borderColor: '#F1F1F1',
        },
      },
    },
    MuiInputBase: {
      styleOverrides: {
        root: {
          padding: 0,
          display: 'flex',
          alignItems: 'flex-start',
          gap: '10px',
          alignSelf: 'stretch',
          backgroundColor: '#F1F1F1',
          borderRadius: '120px',
          color: '#3D3D3D',
          '&.Mui-focused': {
            backgroundColor: 'white!important',
          },
          '&:hover': {
            backgroundColor: '#E5E7EB',
          },
          '&.Mui-error': {
            backgroundColor: 'white!important',
          },
          '&.Mui-disabled': {
            backgroundColor: '#F5F5F7',
            '&:hover': {
              backgroundColor: '#F5F5F7 !important',
            },
          },
        },
      },
    },

Unfortunately, now that I created a global override that works perfectly, I have to account for an additional text input which requires different background and border styles.

How would you handle this? Refactor the TextInput overrides to exclude border/background styling, and then handle the background/border override using styled components? Is this the preferred way to handle this?

Also Is there a way to bundle all of these overrides as a variants of a TextInput instead?

Thanks in advance for any time and energy sent my way!