How to style InputAdornment like notched OutlinedInput?
Asked Answered
E

1

5

I'm using React JS and Material UI framework.

I need the adornment icon color inside a text field to behave like the border of the input.

If you look at the example from the documentation you can see that when:

  • Hovering the input, the border will be wider and black
  • Focusing the input, the border will be wider and have the primary color

I found that these settings come from the styling given to the component.

How can I apply these rules colors to the icon?

Another related question- what is the easiest way to give a color other than primary or secondary? Only by overriding the classes as described in the documentation?

Entrust answered 8/1, 2020 at 22:12 Comment(0)
C
7

Below is an example of how to do this -- the key aspects being the outlinedInput class and (if you also want to sync the label) the textField class. The color could be anything you want to use, but in this example I'm using the same colors from the theme as are used for the border.

import React from "react";
import clsx from "clsx";
import { makeStyles } from "@material-ui/core/styles";
import IconButton from "@material-ui/core/IconButton";
import OutlinedInput from "@material-ui/core/OutlinedInput";
import InputLabel from "@material-ui/core/InputLabel";
import InputAdornment from "@material-ui/core/InputAdornment";
import FormControl from "@material-ui/core/FormControl";
import Visibility from "@material-ui/icons/Visibility";
import VisibilityOff from "@material-ui/icons/VisibilityOff";

const useStyles = makeStyles(theme => ({
  root: {
    display: "flex",
    flexWrap: "wrap"
  },
  margin: {
    margin: theme.spacing(1)
  },
  textField: {
    width: 200,
    "&:hover .MuiInputLabel-root": {
      color: theme.palette.text.primary
    },
    "& .Mui-focused.MuiInputLabel-root": {
      color: theme.palette.primary.main
    }
  },
  outlinedInput: {
    "&:hover .MuiInputAdornment-root .MuiSvgIcon-root": {
      color: theme.palette.text.primary
    },
    "&.Mui-focused .MuiInputAdornment-root .MuiSvgIcon-root": {
      color: theme.palette.primary.main
    }
  }
}));

export default function InputAdornments() {
  const classes = useStyles();
  const [values, setValues] = React.useState({
    password: "",
    showPassword: false
  });

  const handleChange = prop => event => {
    setValues({ ...values, [prop]: event.target.value });
  };

  const handleClickShowPassword = () => {
    setValues({ ...values, showPassword: !values.showPassword });
  };

  const handleMouseDownPassword = event => {
    event.preventDefault();
  };

  return (
    <div className={classes.root}>
      <div>
        <FormControl
          className={clsx(classes.margin, classes.textField)}
          variant="outlined"
        >
          <InputLabel htmlFor="outlined-adornment-password">
            Password
          </InputLabel>
          <OutlinedInput
            id="outlined-adornment-password"
            type={values.showPassword ? "text" : "password"}
            value={values.password}
            onChange={handleChange("password")}
            className={classes.outlinedInput}
            endAdornment={
              <InputAdornment position="end">
                <IconButton
                  aria-label="toggle password visibility"
                  onClick={handleClickShowPassword}
                  onMouseDown={handleMouseDownPassword}
                  edge="end"
                >
                  {values.showPassword ? <Visibility /> : <VisibilityOff />}
                </IconButton>
              </InputAdornment>
            }
            labelWidth={70}
          />
        </FormControl>
      </div>
    </div>
  );
}

Edit Sync adornment color with border

Follow-up questions from the comments:

How to correctly override multiple classes? I see that it works and I understand your explanation, however- it seems that I don't quite understand where I need to add space between the classes names or after '&:hover'. For example in my demo in order to color the label when focused, I wrote "&.Mui-focused.MuiInputLabel-root" while in your demo it's "& .Mui-focused.MuiInputLabel-root" with space after "& ". Of course, the difference is because I applied the styles on InputLabel and you on the TextField, but why does it differ?

The & refers to the CSS class generated for the current style rule (e.g. classes.textField or classes.outlinedInput). The space is a descendant CSS selector. The element with the "MuiInputLabel-root" class is a descendant of the element receiving the classes.textField class, so & .Mui-focused.MuiInputLabel-root successfully targets the label. Without the space, it would only target elements that have the classes.textField class and the MuiInputLabel-root class. If the classes.textField class were being applied to the label element, then that would work, but since we need to target hovering over the entire input rather than just the label, the class needs to be applied to the parent.

Relevant Documentation:

Chastitychasuble answered 8/1, 2020 at 22:47 Comment(5)
Thank you very much! This is exactly what I was looking for :-)Entrust
Another related question, How can I style the label color when hovering? I managed to sync the: text, label, border(notched) and adornment all together with when not focused and when focused. The sync also works when hovering for text border and adornment, but not label. Demo: codesandbox.io/s/…Entrust
I've updated my answer to include label and here's a changed version of your sandbox: codesandbox.io/s/…. Since label is a sibling of the input, you need to control the hover using their common parent -- the FormControl element. FormControl is the root element of TextField so you can target it using the className prop on TextField.Chastitychasuble
Thanks for the great help! Again, Another related question: How to correctly override multiple classes? I see that it works and I understand your explanation, however- it seems that I don't quite understand where I need to add space between the classes names or after '&:hover'. For example in my demo in order to color the label when focused, I wrote "&.Mui-focused.MuiInputLabel-root" while in your demo it's "& .Mui-focused.MuiInputLabel-root" with space after "& ". Of course, the difference is because I applied the styles on InputLabel and you on the TextField, but why does it differ?Entrust
See my additions at the end of the answer.Chastitychasuble

© 2022 - 2024 — McMap. All rights reserved.