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>
);
}
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: