mui / material-ui

Material UI: Ready-to-use foundational React components, free forever. It includes Material UI, which implements Google's Material Design.
https://mui.com/material-ui/
MIT License
92.56k stars 31.91k forks source link

[TextField][InputAdornment] InputLabel should not start shrunken if TextField has an InputAdornment #13898

Open jonas-scytech opened 5 years ago

jonas-scytech commented 5 years ago

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

Tech Version
Material-UI 3.6.1
Material-UI styles 3.0.0-alpha.2
React 16.7.0-alpha.2
Browser Chrome 71.0.3578.98
TypeScript 3.2.1
oliviertassinari commented 5 years ago

@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.

jonas-scytech commented 5 years ago

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.

TidyIQ commented 5 years ago

Any update on this?

eps1lon commented 5 years ago

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.

jonas-scytech commented 5 years ago

https://material.io/design/components/text-fields.html#anatomy

They have a Icons section showing a text field with a start adornment and shrunk label, I assume that if this was not the behaviour for Outlined text field they would say something there or in the dedicated section for the Outlined text field.

Edit: I should have read #14126 first, this was already mentioned there

eps1lon commented 5 years ago

They have a Icons section showing a text field with a start adornment and shrunk label

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.

jonas-scytech commented 5 years ago
Screen Shot 2019-04-23 at 11 32 59

@oliviertassinari had already shared it here

eps1lon commented 5 years ago

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).

TidyIQ commented 5 years ago

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).

TidyIQ commented 5 years ago

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.

eps1lon commented 5 years ago

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).

So we agree. It sounded like @jonas-scytech was arguing that current implementation matches the specification.

TidyIQ commented 5 years ago

Yeah sorry, I misread your comment.

You can almost get it to work properly by making the following changes:

const useStyles= makeStyles(theme => ({
  focused: {
    transform: "translate(12px, 7px) scale(0.75)"
  }
}))

...
<InputLabel
  classes={{ focused: classes.focused }}
  shrink={false}
>
Text
</InputLabel>

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.

jonas-scytech commented 5 years ago

Sorry about the confusion, I meant "text field with a start adornment and NOT shrunk label" :/

jonas-scytech commented 5 years ago

Looks like Material Design have a different behaviour for Text fields with icons and text fields with affixes as seem here: 1 and here:

Screen Shot 2019-04-24 at 12 37 07

But Material-UI treat both as InputAdornment and I think there no easy way to tell each other apart. I will try to split InputAdornment into InputIcon and InputAffix and see if it makes fixing this issue easier.

PsyGik commented 5 years ago

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.

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 hover, focused, disabled, error states. Scraped the whole thing.

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 onFocus and onBlur instead of onChange because it made more sense to me.

import React from "react";

import TextField from "@material-ui/core/TextField";
import { withStyles } from "@material-ui/core/styles";
import InputAdornment from '@material-ui/core/InputAdornment';

const styles = theme => ({
    formControl: {
        left: 30, // this moves our label to the left, so it doesn't overlap when shrunk.
        top: 0,
    },
    disabled: {},
});

class TextFieldIcon extends React.Component {

    constructor(props) {
        super(props);
        this.state = {
            shrink: false // this is used to shrink/unshrink ( is this a correct word? ) the label
        }
    }

    shrinkLabel = (event) => {
        const { onFocus } = this.props;
        this.setState({shrink: true});
        onFocus && onFocus(event); // let the child do it's thing
    };

    unShrinkLabel = (event) => {
        const { onBlur } = this.props;
        if(event.target.value.length === 0) {
            this.setState({shrink: false}) //gotta make sure the input is empty before shrinking the label
        }
        onBlur && onBlur(event); // let the child do it's thing
    };

    render() {
       // make sure to check endIcon and startIcon, we don't need errors in our console
        const { classes, endIcon, autoComplete, startIcon, ...other } = this.props;
        return <TextField {...other}
                          onFocus={this.shrinkLabel}
                          onBlur={this.unShrinkLabel}
                          InputLabelProps={{shrink: this.state.shrink, classes: classes }}
                          InputProps={{
                              autoComplete,
                              endAdornment: endIcon && (
                                  <InputAdornment position={"end"}>
                                      {endIcon}
                                  </InputAdornment>
                              ),
                              startAdornment: startIcon && (
                                  <InputAdornment position={"start"}>
                                     {startIcon}
                                  </InputAdornment>
                              )}}
        />;
    }
}

export default withStyles(styles)(TextFieldIcon);

I honestly believe that this should be baked in the library. I mean, the endAdornment works as in the specs. I'm not sure why the startAdornment doesn't follow the specs. Since I have a workaround for now, I won't complain. 😅Next challenge, get this working with rtl 😓

NoahDavidATL commented 5 years ago

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

TidyIQ commented 5 years ago

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.

oliviertassinari commented 5 years ago

the label should not start "shrunk"

@TidyIQ For sure 👍

kelly-tock commented 4 years ago

Just encountered this as well, its a very strange inconsistency to require the adornments to be an endAdornment to just get it to look and behave like other text fields in the same form.

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.

Cristy94 commented 4 years ago

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.

chenasraf commented 4 years ago

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 :/

richardanewman commented 4 years ago

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.

import React, { useState } from 'react';
import { TextField, InputAdornment, withStyles } from '@material-ui/core';

const PriceField = withStyles({
        //Pushes label to right to clear start adornment
    root: {
        '& label': {
            marginLeft: '3.75rem'
        }
    }
})(TextField);

const StyledInputAdornment = withStyles({
    root: {
                //MUI puts .75rem padding-left by default. Could not override
        //so padding-right is .75 short to offset the difference
        padding: '1.125rem 1.75rem 1.125rem 1rem',
        borderRight: '1px solid #BBC8D8',
        height: 'inherit'
    }
})(InputAdornment);

const ExampleComponent = () => {

const [shrink, setShrink] = useState(false);
    const shrinkLabel = () => {
        setShrink(true);
    };
    const unShrinkLabel = e => {
        if (e.target.value.length === 0) {
            setShrink(false);
        }
    };

return (
        <PriceField
            type="number"
            label="Product Price"
            fullWidth
            onFocus={shrinkLabel}
            onBlur={unShrinkLabel}
            InputLabelProps={{ shrink: shrink }}
            InputProps={{
                startAdornment: currencyForIcon && currencyForIcon.symbol && (
                    <StyledInputAdornment variant="outlined" position="start">
                            {currencyForIcon.symbol}
                    </StyledInputAdornment>
                    )
                }}
            />
    );
};

export default ExampleComponent;
sappster commented 4 years ago

Came across this issue today and @richardanewman got me going in the right direction, and I found a solution for the outline variant with out-of-the-box MUI style. If you override the transform style in the .MuiInputLabel-outlined class. You can have the label offset with the adornment and it will still shrink to the default location with gap. Here is a code snippet:

import React, { Component } from 'react';
import PropTypes from 'prop-types';
import InputAdornment from '@material-ui/core/InputAdornment';
import TextField from '@material-ui/core/TextField';
import SearchIcon from '@material-ui/icons/Search';

import { withStyles, createStyles } from '@material-ui/core/styles';

const styles = (theme) => createStyles({
  labelOffset: {
    transform: "translate(44px, 20px) scale(1)",
  }
});

class TextBox extends Component {
  constructor(props) {
    super(props);

    this.state = {
      shrink: false,
    }

    this.onFocus = this.onFocus.bind(this);
    this.onBlur = this.onBlur.bind(this);
  }

  onFocus(event) {
    this.setState({ shrink: true });
  }

  onBlur(event) {
    if (event.target.value.length === 0)
      this.setState({ shrink: false });
  }

  render() {
    const { classes } = this.props;
    const { shrink } = this.state;

    return(
        <div>
        <TextField
           id="outlined-textarea"
           label="Place Label Here"
           placeholder="Placeholder"
           variant="outlined"
           onFocus={ this.onFocus }
           onBlur={ this.onBlur }
           InputLabelProps={{ shrink: shrink, classes:{ root: classes.labelOffset } }}
           InputProps={{
             startAdornment: (
               <InputAdornment variant="outlined" position="start">
                 <SearchIcon/>
               </InputAdornment>
             )
           }}
         />

        </div>
    );
  }

}

TextBox.propTypes = {
  classes: PropTypes.object.isRequired,
};

export default withStyles(styles)(TextBox);

result: image

This works for me so I can keep going, but I plan to come back an investigate why the shrink gets automatically disabled when a startAdornment is added.

kelly-tock commented 4 years ago

yes, this should just be built in IMO.

TheAschr commented 3 years ago

Here is my solution which works with both outlined and standard text fields (padding for filled is wonky):

        <StartAdornmentTextField
          label="Twitter Handle"
          fullWidth={true}
          startAndornmentText="@"
        />
import React, { useState, useCallback, useRef, useEffect } from "react";
import {
  makeStyles,
  TextField,
  TextFieldProps,
  InputAdornment,
} from "@material-ui/core";
import clsx from "clsx";

type StyleProps = {
  labelOffset: number | undefined;
};

const useStyles = makeStyles((theme) => ({
  inputLabelRoot: {
    display: ({ labelOffset }: StyleProps) =>
      labelOffset !== undefined ? "block" : "none",
    transition: ".3s cubic-bezier(.25,.8,.5,1)",
    marginLeft: ({ labelOffset }: StyleProps) => (labelOffset || 0) + 8,
  },
  inputLabelShrink: {
    marginLeft: () => 0,
  },
}));

export const StartAdornmentTextField: React.FC<
  TextFieldProps & { startAndornmentText: string | number }
> = ({ startAndornmentText, ...props }) => {
  const startAdornmentRef = useRef<HTMLDivElement>(null);

  const [labelOffset, setLabelOffset] = useState<number>();

  useEffect(() => {
    setLabelOffset(startAdornmentRef.current?.offsetWidth);
  }, [startAndornmentText]);

  const classes = useStyles({
    labelOffset,
  });

 const [shrink, setShrink] = useState<boolean>(
    (typeof props.value === "string" && props.value.length !== 0) ||
      (typeof props.value === "number" && String(props.value).length !== 0) ||
      false
  );

  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) {
        setShrink(false);
      }
      if (props.onBlur) {
        props.onBlur(event);
      }
    },
    [props]
  );

  return (
    <TextField
      {...props}
      onFocus={onFocus}
      onBlur={onBlur}
      InputLabelProps={{
        shrink: shrink,
        classes: {
          shrink: clsx(
            classes.inputLabelShrink,
            props.InputLabelProps?.classes?.shrink
          ),
          root: clsx(
            classes.inputLabelRoot,
            props.InputLabelProps?.classes?.root
          ),
          ...props.InputLabelProps?.classes,
        },
        ...props.InputLabelProps,
      }}
      InputProps={{
        startAdornment: (
          <InputAdornment
            ref={startAdornmentRef}
            variant="outlined"
            position="start"
          >
            {startAndornmentText}
          </InputAdornment>
        ),
      }}
    />
  );
};
peteplays commented 3 years ago

I was able to handle this with the following in the theme file. You just need to update the aria-label to match your needs. The spacing is not perfect, but its pretty close. Additionally, it does not mess with the label and has minimal impact on the input spacing.

    MuiIconButton: {
      root: {
        '&[aria-label="toggle password visibility"]': {
          padding: '0 23px 4px 0',
        },
      },
    },

Tweak the padding to match your needs

softwareplumber commented 3 years ago

IMHO this is a bug, not an enhancement.

kelly-tock commented 3 years ago

Could this be addressed in v5?

otaviobonder-deel commented 2 years ago

I extended the very nice example from @TheAschr to add the possibility to add a custom icon prop to the existing TextField:

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 />} />

image image

Suggestions are appreciated

Dentrax commented 2 years ago

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 startAdornment, but works if I set endAdornment. What's the workaround? How can I fix this?

Any updates on this? 🤞

kbooz commented 2 years ago

This is how I fixed using the sx prop only:

search bar

<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!

niklaswallerstedt commented 2 years ago

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: ...
...
ytoubal commented 2 years ago

Any updates on this? I just started using MUI and I stumbled upon this issue

norayr93 commented 1 year ago

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.

BananaHotSauce commented 1 year ago

looks like everyone gave up on this one

BananaHotSauce commented 1 year ago

This gave me a really hard time. but i have hacked around it. feel free to change my code.

`import React,{useState} from "react" import {TextField,InputAdornment,IconButton} from "@mui/material" import VisibilityIcon from '@mui/icons-material/Visibility'; import EmailIcon from '@mui/icons-material/Email'; import PasswordIcon from '@mui/icons-material/Password';

function CustomTextfield({ id, label, endAdornment, startAdornment, isPassword, hasBottomMargin, value, onChange }){

const [shrink,setShrink] = useState(false)
const [meow,setMeow] = useState(false)

const EndAdornment = endAdornment
const StartAdornment = startAdornment

const end_Adornment = endAdornment ? (
        <InputAdornment position='end'>
            <IconButton
            aria-label='toggle password visibility'>
                <EndAdornment />
            </IconButton>
        </InputAdornment>
    ) : null

const start_Adornment = startAdornment ? (
    <InputAdornment position='end'>
        <IconButton
        aria-label='toggle password visibility'>
            <StartAdornment sx={{pl:"0px"}}/>
        </IconButton>
    </InputAdornment>
) : null

const fffff = !value ? {
    '&.MuiInputLabel-root': {
        transform: `translate(54px, 1rem)`,
    },
    '&.Mui-focused': {
    transform: "translate(14px, -9px) scale(0.75)",
    },
    '&.MuiInputLabel-root:not(.Mui-focused) ~ .MuiInputBase-root .MuiOutlinedInput-notchedOutline legend': {
        maxWidth: 0,
    }
} : {}

const labelHack = (startAdornment || endAdornment) ? {
    sx: {
        ...fffff
    }
} : {}

return(
    <>            
        <TextField
            id={id}
            label={label}
            type={isPassword ? 'password' : 'email'}
            InputProps={{
                endAdornment: end_Adornment,
                startAdornment: start_Adornment,
                style: {
                    padding: "0 14px 0 0"
                },
                className:'we-track-custom-texhfield'
            }}
            InputLabelProps={
            {
                ...labelHack

            }}
            fullWidth
            sx={hasBottomMargin ? {mb:2} : {}}
            value={value}
            onChange={e => onChange(e.target.value)}
        />
    </>
)

}

export default CustomTextfield`

MehbubRashid commented 1 year ago

Not very hard to implement.

Animation I faced the issue in the autocomplete component. So i solved it in autocomplete. But the code is same for textfield as well since autocomplete is a wrapper on top of textfield.

Code: You might have to calibrate the transform: translate(x, y) values to suit your input field size.

const [shrink, setShrink] = useState(false);

return (
    <TextField 
        sx={{
            '& .MuiInputLabel-root:not(.MuiInputLabel-shrink)': {
                transform: "translate(41px, 17px)"
            }
        }}
        onFocus={() => setShrink(true)}
        onBlur={(e) => {
            !e.target.value && setShrink(false);
        }}
        label={label} 
        InputProps={{
            startAdornment: (
                <InputAdornment position="start">
                        <DirectionsBusIcon></DirectionsBusIcon>
                </InputAdornment>
            )
        }}
        InputLabelProps={{
            shrink: shrink,
        }}
    />
)
dtrenz commented 1 year ago

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.

fakhamatia commented 1 year ago

Same problem InputLabel not show properly with startAdornment and direction rtl

Demo

        <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>
solomon23 commented 1 year ago

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

<FormControl sx={{ m: 1, width: 300 }}>
        <InputLabel id="practice-location-input">Location</InputLabel>
        <Select
          labelId="practice-location-input"
          multiple
          value={locations}
          onChange={handleLocationChange}
          input={<OutlinedInput label="Location" />}
          renderValue={(selected) => selected.join(', ')}
          MenuProps={MenuProps}
          startAdornment={<VaccinesIcon />}
        >
          {data.locations.map((location) => {
....
          })}
        </Select>
      </FormControl>
mj12albert commented 8 months ago

I will see if we can fix this in ~v6~ v7! https://github.com/mui/material-ui/issues/38374