In my opinion, the effort required for this workaround may not be worth it compared to simply disabling shrink or auto-complete for login. However, the original intention behind this feature was to enhance security by preventing password theft through auto-complete. Once Chrome (and similar browsers) removed these restrictions, React's de-duping mechanism caused the issue we are facing now. There are alternative solutions available, but you can choose the one that suits your needs best.
To address this issue, you can attach a handler to each input
's onAnimationStart
event. This handler can check if the animationName
is "mui-auto-fill"
and whether the input
contains a -webkit-autofill
pseudo class indicating that the browser has auto-filled the field. Additionally, handling the "mui-auto-fill-cancel"
case is necessary in situations where the form gets auto-filled and the user subsequently clears the values to reset the shrink
effect.
For instance:
const [passwordHasValue, setPasswordHasValue] = React.useState(false);
const makeAnimationStartHandler = (stateSetter) => (e) => {
const autofilled = !!e.target?.matches("*:-webkit-autofill");
if (e.animationName === "mui-auto-fill") {
stateSetter(autofilled);
}
if (e.animationName === "mui-auto-fill-cancel") {
stateSetter(autofilled);
}
};
...
<TextField
type="password"
id="password"
inputProps={{
onAnimationStart: makeAnimationStartHandler(setPasswordHasValue)
}}
InputLabelProps={{
shrink: passwordHasValue
}}
label="Password"
value={password}
onChange={(e) => {
setPassword(e.target.value);
...
}}
/>
The expected result upon loading should look like this:
https://i.sstatic.net/RrSXy.png
Updated Version with cancel function - enables the user to clear the form field after auto-fill, which resets the label:
https://i.sstatic.net/3YR1s.png
Just a note: I streamlined my makeAnimationStartHandler
into a single function that accepts a React.useState()
setter as a parameter to minimize code repetition. This allows you to handle manual entry scenarios for each field separately if needed.
Live Example:
CodeSandbox Demo: https://codesandbox.io/s/autofill-and-mui-label-shrink-z3vxm7?file=/Demo.tsx