React Better Placeholders

Nice form input placeholders, an idea stolen directly from Circle's "Adaptive Placeholders" but implemented in react rather than css. See http://blog.circleci.com/adaptive-placeholders/

by Artem

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.13.1/JSXTransformer.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.13.1/react-with-addons.js"></script>
<script src="https://facebook.github.io/react/js/jsfiddle-integration.js"></script>

<div id="container">
    <!-- This element's contents will be replaced with your component. -->
</div>

CSS

*, *:before, *:after {
    -moz-box-sizing: border-box;
    -webkit-box-sizing: border-box;
    box-sizing: border-box;
}

* {
	padding: 0;
	margin: 0;
}

input, textarea {
    width: 100%;
    padding: 10px;
    outline: none;
    border: 1px solid #aaa;
    border-radius: 5px;    
}

textarea {
    height: 100px;
}

label {
    position: absolute;
    cursor: text;
    color: #aaa;
    transition: 0.3s ease-in-out;
}
    
.labeled-field {
    position: relative;
    margin: 10px;
}

.label {
    left: 7px;
    top: -6px;
    font-size: 16px;
    color: #39f;
    background-color: #fff;
    transition: 0.3s ease-in-out;
}

.placeholder {
    left: 10px;
    top: 11px;
    transition: 0.3s ease-in-out;    
}

JavaScript 1.7

var AdaptivePlaceholder = React.createClass({
  createStateFromProps: function(props){
    return {
      label: (props.value ?
        props.label || props.placeholder :
        props.placeholder || props.label),
      style: (props.value ? 'label' : 'placeholder')
    };
  },
  getInitialState: function(){
    return this.createStateFromProps(this.props);
  },
  componentWillReceiveProps: function(props){
    this.setState(this.createStateFromProps(props));
  },
  render: function(){
    return (
      <label
        className={this.state.style}
        onClick={this.props.onClick}>{this.state.label}</label>
    );
  }
});

var LabeledField = React.createClass({
    getInitialState: function(){
        return {
            value: this.props.value
        };
    },
    handleChange: function(ev) {
        this.setState({
            value: ev.target.value
        });
    },
    handleLabelClick: function(ev){
      this.refs.in.getDOMNode().focus();
    },
    render: function() {
        var field = React.addons.cloneWithProps(
            React.Children.only(this.props.children), {
                ref: 'in', 
                onChange: this.handleChange
            });
        return (
            <div className='labeled-field'>
                {field}
                <AdaptivePlaceholder 
                    {... this.props}
                    value={this.state.value}
                    onClick={this.handleLabelClick}/>
            </div>
        );
    }
});
 
React.render(
    <form>
        <LabeledField placeholder="Enter a title" label="Title">
          <input type="text" />
        </LabeledField>
        <LabeledField placeholder="Enter your name" label="Your name is">
          <input type="text" />
        </LabeledField>
        <LabeledField placeholder="Tell us a story" label="Your story">
          <textarea />
        </LabeledField>
    </form>, document.body);