Material-ui: [TextField] Add icon prop to Text Field

Created on 14 Jan 2016  ·  30Comments  ·  Source: mui-org/material-ui

As referenced in #2416, we currently don't have a way to add a left icon to the Text Field component. I'd like to work on a PR for this.

TextField would be called like<TextField icon={icon} /> and would render the icon on the left side in the textField before the input.

TextField enhancement good first issue

Most helpful comment

The easiest way to achieve the icon adjacent to the text field is to wrap the field and icon in a div that can contain the absolute positioned icon.

<div style={{position: 'relative', display: 'inline-block'}}>
      <SearchIcon style={{position: 'absolute', right: 0, top: 15, width: 20, height: 20}}/>
      <TextField
           hintText="Search by Name"
           onChange={_.debounce((event, value) => this.handleSearch(value), 500)}
        />
</div>

search-bar-with-icon

If you want it on the left, simply add a textIndent to the field and change the positioning to the left.

<div style={{position: 'relative', display: 'inline-block'}}>
       <SearchIcon style={{position: 'absolute', left: 0, top: 15, width: 20, height: 20}}/>
       <TextField
              style={{textIndent: 30}}
              hintText="Search by Name"
              onChange={_.debounce((event, value) => this.handleSearch(value), 500)}
        />
</div>

search-bar-with-left-icon

If you want to have dynamic icons, then change the field onChange method to update the state which can change the icon. If you wanted to make this cleaner, you can put this in a component and call it IconTextField like } ....other attributes />

All 30 comments

As pointed out by #3032, it could look like
screen shot 2016-01-24 at 12 55 58 pm
and #3038 we should be able to add an icon on the left and on the right.

also would be great to see prefix and suffix
image

I'd like something like this. Are you working on this?

How long will it be before this will be released?

I think this should be extended to the autocomplete input too, would be very useful.

Could there be a way to add an icon with TextField validations/errors also?
screen shot 2016-07-05 at 1 19 31 pm

slice 1

I think that should apply to all "form" fields, including SelectField.

I accomplish that using TextField inside ListItem or MenuItem. Put a TextField inside ListItem then use leftIcon or rightIcon props to achieve it.

I accomplish that using TextField inside ListItem or MenuItem.

I think that it's the right approach. I would rather use composition over additional logic in the TextField.
However, I'm wondering if ListItem or MenuItem were designed with this use case in mind.
I think that we could have a more specified component to do it. Like a <TextFieldIcon />

I think the best would be to have it in what looks like a ListItem like shown here: https://material.google.com/components/text-fields.html#text-fields-single-line-text-field

And perhaps have it as a similar option to rightCheckbox, but then rightField, and possible support giving it an array of max. 2 elements, like TextField and/or SelectField, like shown in that phone/calendar example.

This could save a lot of space especially on mobile, and hassle, not needing to tweak the css just right to have them all align.

The issue with using a Textfield nested with ListItem is that... unless I am missing something, it becomes impossible to tab to the next Textfield in your form.

For this reason alone it is preferable to have a standalone as suggested by @oliviertassinari or simply an additional prop that can be set on , although the latter seems to be discouraged by #4027. Has anyone found a working workaround?

Is there any progress or temporary solution to solve the original issue?

@iamzhouyi try to use something like this for autocomplete experience

<Menu disableAutoFocus>
  <MenuItem leftIcon={<SearchIcon color='#fff'/>} disabled>
    <AutoComplete hintText='Search' />
  </MenuItem>
</Menu> 

Anyone with any progress on this? If anyone has started I'd love to help, if not I'd give it a whirl myself?

Doesn't look like it @oshalygin, note it's been added to the checklist on #6566 though so might want to track progress there!

Would be a great addition.

@oshalygin If you're going to look into this, I'd suggest working off the next branch - we aren't prioritizing new features on master. Also, because it is made of composable components, you should find it easier.

I think it also would be great to have circular progress in text fields for real time checking of the text field value.

Wow, I see this was opened 1.5 years ago! Any update to this? I've tried adding CSS hacks (&before content) which kind of work, but I need more fine grained control, as I need to style it further, have it disappear or go away depending on state, and more specifically, be inside the textfield. Tried fiddling also w/ the HintText/placeholder, but all of these are totally conflicting and chaotic with each other. 😞

The easiest way to achieve the icon adjacent to the text field is to wrap the field and icon in a div that can contain the absolute positioned icon.

<div style={{position: 'relative', display: 'inline-block'}}>
      <SearchIcon style={{position: 'absolute', right: 0, top: 15, width: 20, height: 20}}/>
      <TextField
           hintText="Search by Name"
           onChange={_.debounce((event, value) => this.handleSearch(value), 500)}
        />
</div>

search-bar-with-icon

If you want it on the left, simply add a textIndent to the field and change the positioning to the left.

<div style={{position: 'relative', display: 'inline-block'}}>
       <SearchIcon style={{position: 'absolute', left: 0, top: 15, width: 20, height: 20}}/>
       <TextField
              style={{textIndent: 30}}
              hintText="Search by Name"
              onChange={_.debounce((event, value) => this.handleSearch(value), 500)}
        />
</div>

search-bar-with-left-icon

If you want to have dynamic icons, then change the field onChange method to update the state which can change the icon. If you wanted to make this cleaner, you can put this in a component and call it IconTextField like } ....other attributes />

@bradrisse works great, thank god I read the whole thread, found the answer I was looking in the last comment

Is it possible to add as props?
_ floatingLabelText='Label'
hintText='Hint Text'
errorText={${<MoreVertIcon />} Error Text}
multiLine
/>_

import ActionHome from 'material-ui/svg-icons/action/home';
<TextField
floatingLabelText={<SvgIconComponent/>}
floatingLabelFixed={true}
/>

// textfield with icon
const IconTextField = (props) => (

icon={"person"}
hintText={props.label}
type={props.type ? props.type : 'text'}
fullWidth={true}
/>

)

I believe this can be closed, right ? https://material-ui-next.com/demos/text-fields/#input-adornments

@stunaz I don't think that it's what people are asking for here.

@oliviertassinari The only other type I can see in the spec is "Icon signifier":

Icon signifier

Icons describe the type of input a text field requires. They are displayed to the left of the text field.

It seems that can be acheived with only a few lines of code:

image

const styles = theme => ({
  icon: {
    margin: '20px 16px 0 0',
    color: theme.palette.action.active,
  },
});

[...]

<div>
    <Person className={classes.icon} />
    <TextField label="Name" />
</div>

Would an example in the docs allow us to close this issue?

@mbrookes I have an idea. Since text field is not the only component that want an icon decorator, maybe we can make a wrapper that will append icon to an element.

Example

For text field

<IconDecorator icon={<PeopleIcon/>} position="left" iconStyle={customStyle}>
    <TextField label="Name"/>
</IconDecorator>

For button

<IconDecorator icon={<ArrowRightIcon/>} position="right" iconStyle={customStyle}>
    <Button raised={true}>Go</Button>
</IconDecorator>

Advantage

This method will not break or pollute the current API, thus there will be no breaking changes.

Concern

If this IconDecorator is to be implemented, should it be included in this library or another external library?

@wongjiahau The one difficulty I see with that is that the vertical alignment is component specific, so it would have to check it's child type and adjust its margins appropriately, but that can be acheived.

If this was to go ahead, it makes sense for it to be part of MUI.

@oliviertassinari sorry to page you, but this needs your insight & experience.

This appears to still be open? Did it get kicked or is it still looking to be resolved?

@BlakeBurnette This issue is about exposing a specific component for handling this issue case. I'm not 💯 % convinced it's needed given the two following alternatives. Does anyone want to add a demo to the documentation so we can close this issue?

capture d ecran 2018-03-27 a 21 02 12
https://codesandbox.io/s/29yj0lr7p

import React from "react";
import PropTypes from "prop-types";
import { withStyles } from "material-ui/styles";
import Input, { InputLabel, InputAdornment } from "material-ui/Input";
import { FormControl } from "material-ui/Form";
import TextField from "material-ui/TextField";
import Grid from "material-ui/Grid";
import AccountCircle from "material-ui-icons/AccountCircle";

const styles = theme => ({
  margin: {
    margin: theme.spacing.unit
  }
});

function TextFieldIcons(props) {
  const { classes } = props;

  return (
    <div>
      <FormControl className={classes.margin}>
        <InputLabel htmlFor="demo1">First Name</InputLabel>
        <Input
          id="demo1"
          startAdornment={
            <InputAdornment position="start">
              <AccountCircle />
            </InputAdornment>
          }
        />
      </FormControl>
      <TextField
        className={classes.margin}
        id="demo2"
        label="First Name"
        InputProps={{
          startAdornment: (
            <InputAdornment position="start">
              <AccountCircle />
            </InputAdornment>
          )
        }}
      />
      <div className={classes.margin}>
        <Grid container spacing={8} alignItems="flex-end">
          <Grid item>
            <AccountCircle />
          </Grid>
          <Grid item>
            <TextField id="demo2" label="First Name" />
          </Grid>
        </Grid>
      </div>
    </div>
  );
}

TextFieldIcons.propTypes = {
  classes: PropTypes.object.isRequired
};

export default withStyles(styles)(TextFieldIcons);
Was this page helpful?
0 / 5 - 0 ratings

Related issues

mattmiddlesworth picture mattmiddlesworth  ·  3Comments

ghost picture ghost  ·  3Comments

revskill10 picture revskill10  ·  3Comments

iamzhouyi picture iamzhouyi  ·  3Comments

anthony-dandrea picture anthony-dandrea  ·  3Comments