Material-ui: [TextField] Improve outlined variant customization

Created on 22 Oct 2018  路  14Comments  路  Source: mui-org/material-ui

The documentation doesn't mention the class name to customize the outline when using a Textfield with the outlined variant.

  • [x] This is not a v0.x issue.
  • [x] I have searched the issues of this repository and believe that this is not a duplicate.

Expected Behavior

In the Input api page, the CSS Api should list the notchedOutline class property name.

Current Behavior

Currently there is nothing in the documentation that allow us to know how to customize the outline.

Context

Changing the color of the border.

Your Environment

| Tech | Version |
|--------------|---------|
| Material-UI | v3.3.0 |

TextField enhancement important

Most helpful comment

@serendipity1004: Let us know what you think:

import React from "react";
import { withStyles } from "@material-ui/core/styles";
import TextField from "@material-ui/core/TextField";
import purple from "@material-ui/core/colors/purple";

const styles = theme => ({
  root: {
    "&:hover:not($disabled):not($focused):not($error) $notchedOutline": {
      borderColor: purple[500]
    }
  },
  disabled: {},
  focused: {},
  error: {},
  notchedOutline: {}
});

function CustomizedInputs(props) {
  return (
    <TextField
      InputProps={{ classes: props.classes }}
      label="Custom CSS"
      variant="outlined"
      id="custom-css-outlined-input"
    />
  );
}

export default withStyles(styles)(CustomizedInputs);

https://codesandbox.io/s/ry26oj1rkq

All 14 comments

We could maybe improve the documentation and say that the input part is mostly a switch for Input | OutlinedInput | FilledInput. Basically extend the part in https://material-ui.com/api/text-field/#advanced-configuration to mention the used component depending on the variant.

@eps1lon You just made me realize that the input part is switch according the variant.

Indeed, in that case that would be totally more understandable if there will be something to indicates that the InputProps is used for Input || OutlinedInput || FilledInput according to the selected variant.

Changing the color of the border.

It's the same concern as with https://github.com/mui-org/material-ui/pull/13105#issuecomment-427320778

The customization story was overlooked when implementing this outlined variant. Right now, you can change the color like this:

import React from "react";
import PropTypes from "prop-types";
import { withStyles } from "@material-ui/core/styles";
import TextField from "@material-ui/core/TextField";

const styles = theme => ({
  notchedOutline: {},
  focused: {
    "& $notchedOutline": {
      borderColor: "yellow"
    }
  }
});

class OutlinedTextFields extends React.Component {
  state = {
    name: "Cat in the Hat"
  };

  handleChange = name => event => {
    this.setState({
      [name]: event.target.value
    });
  };

  render() {
    const { classes } = this.props;

    return (
      <form className={classes.container} noValidate autoComplete="off">
        <TextField
          id="outlined-name"
          label="Name"
          InputProps={{
            classes: {
              notchedOutline: classes.notchedOutline,
              focused: classes.focused
            }
          }}
          value={this.state.name}
          onChange={this.handleChange("name")}
          variant="outlined"
        />
      </form>
    );
  }
}

OutlinedTextFields.propTypes = {
  classes: PropTypes.object.isRequired
};

export default withStyles(styles)(OutlinedTextFields);

https://codesandbox.io/s/7jpl38xm1x

Going forward, I think that we should extract the state logic style out from the private NotchedOutline.js component and move it to the OutlinedInput.js component.

@serendipity1004 It's important that people are able to easily customize our components, especially the text field as it's one of the most used. We have been working on this problem in #13428. It's in master but not released yet (later this evening). You can check it out in here: https://material-ui.netlify.com/demos/text-fields/#customized-inputs.

Basically, you can either 1. change it at the theme level or 2. with CSS overrides:

const styles = {
  cssLabel: {
    '&$cssFocused': {
      color: purple[500],
    },
  },
  cssOutlinedInput: {
    '&$cssFocused $notchedOutline': {
      borderColor: purple[500],
    },
  },
  cssFocused: {},
  notchedOutline: {},
}

// ...

<TextField
  className={classes.margin}
  InputLabelProps={{
    classes: {
      root: classes.cssLabel,
      focused: classes.cssFocused,
    },
  }}
  InputProps={{
    classes: {
      root: classes.cssOutlinedInput,
      focused: classes.cssFocused,
      notchedOutline: classes.notchedOutline,
    },
  }}
  label="Custom CSS"
  variant="outlined"
  id="custom-css-outlined-input"
/>

Let me know if that works for you, I'm happy to push it further if it's still too complicated.

@oliviertassinari Hi, thank you for answering. It's not complicated for what you have provided; however, I am still not able to get the "HOVER" color changed which was my original question. Not focused, not root color but HOVER.

I have tried adding &:hover to various style you have suggested but HOVER color is always black (when not focused).

    cssFocused:{
        '&:hover':{
            borderColor:'#FFFFFF'
        }
    },
    cssOutlinedInput: {
        '&$cssFocused $notchedOutline': {
            borderColor: '#448cff',
        },
        '&:hover $notchedOutline':{
            borderColor:'#FFFFFF'
        }
    },
    notchedOutline: {
        borderColor:'#FFFFFF',
        '&:hover':{
            borderColor:'#FFFFFF'
        }
    },

@serendipity1004: Let us know what you think:

import React from "react";
import { withStyles } from "@material-ui/core/styles";
import TextField from "@material-ui/core/TextField";
import purple from "@material-ui/core/colors/purple";

const styles = theme => ({
  root: {
    "&:hover:not($disabled):not($focused):not($error) $notchedOutline": {
      borderColor: purple[500]
    }
  },
  disabled: {},
  focused: {},
  error: {},
  notchedOutline: {}
});

function CustomizedInputs(props) {
  return (
    <TextField
      InputProps={{ classes: props.classes }}
      label="Custom CSS"
      variant="outlined"
      id="custom-css-outlined-input"
    />
  );
}

export default withStyles(styles)(CustomizedInputs);

https://codesandbox.io/s/ry26oj1rkq

@oliviertassinari YAY it works now. Thanks!

I have two Inputs with different styles
I need the TextInputBlackUnderline to have a different hover color for the Input borderBottom

I tried @oliviertassinari's solution, but it didn't work for me, here's my use case:

import React from 'react';
import FormControl from '@material-ui/core/FormControl';
import FormHelperText from '@material-ui/core/FormHelperText';
import InputLabel from '@material-ui/core/InputLabel';
import Input from '@material-ui/core/Input';

import { withStyles } from '@material-ui/core/styles';

const whiteUnderLineStyle = {
    root: {
        width: '100%',
        color: '#fff'
    },
    focused: {
        '&:before': {
            borderBottom: '1.2px solid rgb(186, 47, 125)',
        },
        '&:after': {
            borderBottom: '2px solid rgb(186, 47, 125)',
        },
    },
    underline: {
        '&:before': {
            borderBottom: '1.2px solid #fff',
        },
    }
}

const blackUnderLineStyle = theme => ({
    root: {
        width: '100%',
        color: '#636F88',
        "&:hover:not($disabled):not($focused):not($error) $notchedOutline": {
            borderColor: '#636F88'
        }
    },
    focused: {
        '&:before': {
            borderBottom: '1.2px solid rgb(186, 47, 125)',
        },
        '&:after': {
            borderBottom: '2px solid rgb(186, 47, 125)',
        },
    },
    underline: {
        '&:before': {
            borderBottom: '1.2px solid #636F88',
        },
    }
})

const TextInput = ({ classes, label, onChange, value, errorText, errorTextStyles, inputLabelColor }) => (
    <FormControl classes={{ root: classes.root }}>
        <InputLabel style={{ color: inputLabelColor }}>{ label }</InputLabel>
        <Input
            onChange={ onChange }
            value={ value }
            classes={{
                root: classes.root,
                underline: classes.underline,
                focused: classes.focused
            }} />
        {
            errorText && 
            <FormHelperText style={ errorTextStyles }>
                { errorText }
            </FormHelperText>
        }
    </FormControl>
)

const TextInputWhiteUnderline = withStyles(whiteUnderLineStyle)(TextInput)
const TextInputBlackUnderline = withStyles(blackUnderLineStyle)(TextInput)

export {
    TextInputWhiteUnderline,
    TextInputBlackUnderline
}

@rbenvenuto The example with the :hover property that @oliviertassinari said was for the TextField component.

For you case you should just remove the $notchedOutline, add the :before selector and you will got something like :

    root: {
        width: '100%',
        color: '#636F88',
        '&:hover:not($disabled):not($focused):not($error):before' : {
            borderColor: '#636F88' /*it's possible you need to add the "!important".... Which is not very pretty though */
        }
    },
    focused: {
        '&:before': {
            borderBottom: '1.2px solid rgb(186, 47, 125)',
        },
        '&:after': {
            borderBottom: '2px solid rgb(186, 47, 125)',
        },
    },
    underline: {
        '&:before': {
            borderBottom: '1.2px solid #636F88',
        },
    }

I have a related issue but trying to customize the component overriding the theme.
I want to change these colors for the whole app in the global theme.

If I put in my theme:

    MuiOutlinedInput: {
      notchedOutline: {
        borderColor: '#e0e0e0'
      },
      focused:{
        borderColor: '#607d8b'
      },
    },

The notchedOutline border-color is overridden correctly but not the focus state. Looks like the focus state related css is only defined in MuiPrivateNotchedOutline which one is "private" and I cannot override :/

@francoiscabrol Did you have a look at our customization demo? You should have a warning in your console when doing the above.

I have no warning... I used the doc https://material-ui.com/customization/themes/#customizing-all-instances-of-a-component-type

@francoiscabrol I have the following warning in my console when trying your example:

capture d ecran 2019-01-05 a 22 20 47

You should find what you are looking for in this demo: https://material-ui.com/demos/text-fields/#customized-inputs. While the NotchedOutline component is private, it can still be customized. We use CSS inheritance. On a side note, you can always nest the MuiThemeProvider with your custom color. It can be easier than handling CSS class names.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

iamzhouyi picture iamzhouyi  路  3Comments

activatedgeek picture activatedgeek  路  3Comments

FranBran picture FranBran  路  3Comments

rbozan picture rbozan  路  3Comments

ghost picture ghost  路  3Comments