Personally, I don't think the juice is worth the squeeze for this vs just disabling shrink or auto-complete for the log-in, but no one asked my opinion, so...
From what I understand, the reason this is more painful than we'd like is because it was originally intended as a security feature to prevent password theft via auto-complete, but once Chrome (et al.) removed the restrictions, React's de-duping mechanism took over. There are some slightly more hack-y work-arounds than what I'm going to suggest, but you can decide which you like.
To side-step this, you can add a handler to each input
's onAnimationStart
event, check if the animationName
is "mui-auto-fill"
, and then check if the input
has a -webkit-autofill
pseudo class, to see if the browser has auto-filled the field. You'll also want to handle the "mui-auto-fill-cancel"
case for scenarios where the form is auto-filled and the user clears the values (to reset shrink
.)
For example:
const [passwordHasValue, setPasswordHasValue] = React.useState(false);
// For re-usability, I made this a function that accepts a useState set function
// and returns a handler for each input to use, since you have at least two
// TextFields to deal with.
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 result on load should appear as:
Update with cancel -- allows user to clear out the form field, after load with auto-fill, and the label is reset:
FYI: I made my makeAnimationStartHandler
a function that accepts a React.useState()
setter as a param and returns a handler that actually does the work because your example has two fields and I wanted to 1) reduce code and 2) allow you to still handle the manual entry use-case for each field separately, if desired.
Working Example: https://z3vxm7.csb.app/
Working CodeSandbox: https://codesandbox.io/s/autofill-and-mui-label-shrink-z3vxm7?file=/Demo.tsx
onInput
ininputProps
instead ofonChange
. But I'm not sure it's working for you. – Bova