-
-
Notifications
You must be signed in to change notification settings - Fork 32.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[TextField][InputAdornment] InputLabel should not start shrunken if TextField has an InputAdornment #13898
Comments
@jonas-scytech Right now, we don't support this case to simplify the text field implementation. It can potentially bloat everybody bundle, for a limited value. To investigate. |
Ok, I understand, thank you. I don't have time now, but I will look at this later and see if I find a solution with a small footprint. |
Any update on this? |
We discussed this before and I agree that the label shouldn't start shrunk with an input adornment. There was some discussion in #14126 with a lot of confusion around how it should look. IMO I don't see any issue with the MWC implementation. There were some points raised that the label "clashes" with the adornment but that happens during transition. I don't think anybody cares that the label is in front of the adornment for ~10 frames. I'm still missing a spec example that confirms our implementation. As far as I can tell it should never start shrunk regardless of start adornment or not. |
https://material.io/design/components/text-fields.html#anatomy They have a Edit: I should have read #14126 first, this was already mentioned there |
Could you include a screenshot? I can't find text fields in the linked document that have a start adornment, no input and a shrunk label. |
@oliviertassinari had already shared it here |
Do you mean the third example? The label is shrunk because the text field has an input value not because of the adornment (as is shown in the first example). |
No, the first example. That's how it should look when there is no input value, but currently in MUI it starts off shrunk (like examples 2 and 3 except without any input value). |
I really think this needs to be a big focus. It's the only component I've encountered in all of Material-UI that doesn't match the Material Design specs and looks substantially worse because of it. |
So we agree. It sounded like @jonas-scytech was arguing that current implementation matches the specification. |
Yeah sorry, I misread your comment. You can almost get it to work properly by making the following changes:
This results in the label starting in the non-shrink state (as per MD specs), then shrinks appropriately when focused. The only issue with it is that it doesn't stay in the shrink-state after the user clicks out. It expands back to the full size which causes the label to overlap the input value. If anyone knows how to keep it in the shrink-state when 1) not in focus, AND 2) has user input, then that's at least a workaround for now. edit: Actually I should probably be able to solve this using state. I'll give it a go and will let you know if it works. edit 2: Yep, got it working properly using state! The shrink prop on the label component is equal to a boolean state value, which gets changed using the onChange prop in the input component (based on event.target.value.length. If > 0 then set to true, if === 0 then set to false). You still need to use a class override for 'focused' for the initial focus before the user inputs any text, and I also had to create another class override for 'marginDense' as I've set margins='dense' on my formcontrol component. Finally! I wish I thought of this sooner. It's been bugging me for the longest time. |
Sorry about the confusion, I meant "text field with a start adornment and NOT shrunk label" :/ |
My initial approach to solve this was to extend the bottom-border (or underline if you may) to cover the icon as well. As I progressed I saw that I wrote a lot of code maintaining the Based on the inputs from @TidyIQ (You're a champion!!! 🙌 ) this is what I was able to come up with for my use case. I used
I honestly believe that this should be baked in the library. I mean, the |
The InputAdornment API seemed to have been updated with V4 release, but it still doesn't work: https://codesandbox.io/s/pznrz -- this has been the biggest thorn in my side. Why can't it work like a normal text box, with a little adornment added to the front. Also, the Github link appears to be broken: https://github.com/mui-org/material-ui/blob/master/docs/src/pages/demos/text-fields/ShrinkAuto.js |
Just a quick FYI to further prove that the label should not start "shrunk". The official Material Design docs now has an interactive demo at https://material.io/design/components/text-fields.html#text-fields-single-line-text-field In the configuration options, click "Leading icon". You can see that the label starts "unshrunken" and only shrinks when text is entered. |
@TidyIQ For sure 👍 |
Just encountered this as well, its a very strange inconsistency to require the adornments to be an https://material-components.github.io/material-components-web-catalog/#/component/text-field in the demos section all variants are behaving the same way regardless or adornment start or end. |
Any updates on this? This is a pretty common use case, most header search inputs for example have a search icon, and it should not be in minimzed state. |
I was so happy to finally refactor our website to use MUI, and then the first thing I tried to change - the text inputs - I immediately ran into this problem, our designs are full of inputs that slide the label up on focus, regardless whether it has an icon/adornment or not. The offset needs to be modified still. Will this be worked on soon? 🙌 Or maybe a good workaround?... @PsyGik and @TidyIQ's solutions didn't work for me :/ |
Had the same issue, so want to share my solution. Big thanks to @PsyGik for sharing his solution, which I borrowed to come up with this one. Please let me know if you see any room for improvement. I just started working with React, so I could definitely be missing something. But so far, so good. It's working. Apologies about the formatting. Github isn't liking tabs right now.
|
I extended the very nice example from @TheAschr to add the possibility to add a custom icon prop to the existing import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { InputAdornment, TextField as MuiTextField } from '@mui/material';
import {
StandardTextFieldProps as STFP,
FilledTextFieldProps as FTFP,
OutlinedTextFieldProps as OTFP,
} from '@mui/material';
interface CommonTextFieldProps {
startIcon?: React.ReactNode;
}
type TextFieldProps =
| (CommonTextFieldProps & STFP)
| (CommonTextFieldProps & FTFP)
| (CommonTextFieldProps & OTFP);
interface StyleProps {
labelOffset?: number;
}
const textFieldStyles = ({ labelOffset }: StyleProps) => {
return {
inputLabelRoot: {
transition: '300ms cubic-bezier(.25, .8, .5, 1)',
marginLeft: labelOffset ? `${(labelOffset || 0) + 20}px` : '1px',
},
inputAdornment: {
marginTop: '5px!important',
},
};
};
const TextField = (props: TextFieldProps) => {
const { startIcon, ...rest } = props;
const startAdornmentRef = useRef<HTMLDivElement>(null);
const [labelOffset, setLabelOffset] = useState<number>();
const [shrink, setShrink] = useState<boolean>(
(typeof props.value === 'string' && props.value.length !== 0) ||
(typeof props.value === 'number' && String(props.value).length !== 0) ||
!!props.InputProps?.startAdornment ||
false
);
const styles = useMemo(() => textFieldStyles({ labelOffset }), [labelOffset]);
useEffect(() => {
setLabelOffset(startAdornmentRef.current?.offsetWidth);
}, [startIcon]);
const onFocus = useCallback(
(event: React.FocusEvent<HTMLInputElement | HTMLTextAreaElement>) => {
setShrink(true);
if (props.onFocus) {
props.onFocus(event);
}
},
[props]
);
const onBlur = useCallback(
(event: React.FocusEvent<HTMLInputElement | HTMLTextAreaElement>) => {
if (event.target.value.length === 0 && !props.InputProps?.startAdornment) {
setShrink(false);
}
if (props.onBlur) {
props.onBlur(event);
}
},
[props]
);
const StartAdornment = useMemo(() => {
if (startIcon) {
return (
<InputAdornment sx={styles.inputAdornment} position="start" ref={startAdornmentRef}>
{startIcon}
</InputAdornment>
);
}
}, [startIcon, styles.inputAdornment]);
return (
<MuiTextField
{...rest}
onFocus={onFocus}
onBlur={onBlur}
sx={{
'& .MuiFilledInput-input': {
marginLeft: labelOffset ? `${(labelOffset || 0) - 13}px` : 0,
},
...props.sx,
}}
InputLabelProps={{
shrink,
sx: {
...styles.inputLabelRoot,
},
...props.InputLabelProps,
}}
InputProps={{
startAdornment: StartAdornment,
...props.InputProps,
}}
/>
);
}; So you can use it like: <TextField label="I am an input" startIcon={<Icon.Magnifier />} /> Suggestions are appreciated |
Almost 4 years passed since the issue, I'm newbie at material-ui, and eventually I had this problem and I'm here: <TextField
margin="normal"
required
fullWidth
id="outlined-required"
label="NAME"
InputProps={{
startAdornment: (
<InputAdornment position="start">
<ReceiptIcon />
</InputAdornment>
),
}}
/> Label animation does not work if i pass Any updates on this? 🤞 |
This is how I fixed using the sx prop only: <TextField
InputLabelProps={{
sx: {
'&.MuiInputLabel-root': {
transform: `translate(36px, 0.5rem)`,
},
'&.Mui-focused': {
transform: "translate(14px, -9px) scale(0.75)",
},
'&.MuiInputLabel-root:not(.Mui-focused) ~ .MuiInputBase-root .MuiOutlinedInput-notchedOutline legend': {
maxWidth: 0,
}
}
}}
InputProps={{
startAdornment:(<InputAdornment position="start" ><SearchIcon /></InputAdornment>),
size: "small"
}}
/> The translate values are currently totally arbitrary and customized for the "small" size variant, so feel free to change it! |
The way I went about it was inspired from previous suggestions in the thread. Something like this, you will need to adapt the initial value depending on if you have any data at first in the text field. const [shrink, setShrink] = React.useState(false); <TextField
onFocus={() => setShrink(true)}
onBlur={(e) => {
!e.target.value && setShrink(false);
}}
InputLabelProps={{
shrink: shrink,
}}
startAdornment: ...
... |
Any updates on this? I just started using MUI and I stumbled upon this issue |
Would be great if you could provide some easy workaround to toggle that behavior.I believe there are some edge cases that you haven't included that yet, but maybe some scenarios don't face that edge cases and the important aspect of the field is not working properly. |
looks like everyone gave up on this one |
This gave me a really hard time. but i have hacked around it. feel free to change my code. `import React,{useState} from "react" function CustomTextfield({
} export default CustomTextfield` |
Disappointed to come across this abandoned issue. I'm getting hit by it today. I appreciate that devs have provided some workarounds, but it feels bad to have to add local state and implement event handlers just to get the text field component to behave as it should. |
Same problem <FormControl sx={{ m: 1, width: '25ch' }} 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')}
style={{ direction: "rtl" }}
startAdornment={
<InputAdornment position="start">
<IconButton
aria-label="toggle password visibility"
onClick={handleClickShowPassword}
onMouseDown={handleMouseDownPassword}
edge="start"
>
{values.showPassword ? <VisibilityOff /> : <Visibility />}
</IconButton>
</InputAdornment>
}
label="Password"
/>
</FormControl> |
June 2023 this is still a problem - trying to add a start adornment to a multi select and it the label moves as if it has focus
|
I will see if we can fix this in |
Expected Behavior
Input label should start on its normal position, as seen here:
https://material-components.github.io/material-components-web-catalog/#/component/text-field
Current Behavior
Input label starts shrunken
Steps to Reproduce
https://material-ui.com/demos/text-fields/#outlined-input-adornments
Your Environment
The text was updated successfully, but these errors were encountered: