stackoverflow 24019431
See https://stackoverflow.com/a/44249984/990356
HTML
<script src="https://unpkg.com/[email protected]/umd/react.development.js"></script>
<script src="https://unpkg.com/[email protected]/umd/react-dom.development.js"></script>
<div id="app"></div>
SCSS
.adaptive_placeholder_input_container {
position: relative;
}
.adaptive_input {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
width: 200px;
height: 40px;
border: 3px solid #aaaaaa;
/*border-radius*/
-webkit-border-radius: 10px;
-moz-border-radius: 10px;
border-radius: 10px;
margin: 0 0 1em;
padding: 1em;
background: #fff;
resize: none;
outline: none;
box-shadow: none;
}
.adaptive_input:focus {
border-color: #00bafa;
}
.adaptive_input:focus + .adaptive_placeholder:before {
color: #00bafa;
}
.adaptive_input:focus + .adaptive_placeholder:before, .adaptive_input:valid + .adaptive_placeholder:before {
/*transition-duration*/
-webkit-transition-duration: .2s;
-moz-transition-duration: .2s;
-o-transition-duration: .2s;
transition-duration: .2s;
/*transform*/
-webkit-transform: translate(0, -16px) scale(0.9, 0.9);
-moz-transform: translate(0, -16px) scale(0.9, 0.9);
-ms-transform: translate(0, -16px) scale(0.9, 0.9);
-o-transform: translate(0, -16px) scale(0.9, 0.9);
transform: translate(0, -16px) scale(0.9, 0.9);
}
.adaptive_input:invalid + .adaptive_placeholder:before {
content: attr(alt);
box-shadow: none;
}
.adaptive_input + .adaptive_placeholder {
pointer-events: none;
line-height: 1em;
position: absolute;
left: 10px;
top: 10px;
}
.adaptive_input + .adaptive_placeholder:before {
font-family: Verdana, Geneva, sans-serif;
content: attr(placeholder);
display: inline-block;
padding: 0 2px;
color: #898989;
/*transition*/
-webkit-transition: 0.3s ease-in-out;
-moz-transition: 0.3s ease-in-out;
-o-transition: 0.3s ease-in-out;
transition: 0.3s ease-in-out;
background-color: #ffffff;
}
.adaptive_placeholder_input_container.error {
> .adaptive_input {
border-color: red;
}
> .adaptive_placeholder:before {
color: red;
}
}
.adaptive_placeholder_input_container.warning {
> .adaptive_input {
border-color: orange;
}
> .adaptive_placeholder:before {
color: orange;
...
Babel + JSX
const { FormWithConstraints, FieldFeedbacks, FieldFeedback } = ReactFormWithConstraints;
class Adaptive_Input extends React.Component {
static contextTypes = {
form: PropTypes.object.isRequired
};
constructor(props) {
super(props);
this.state = {
field: undefined
};
this.fieldWillValidate = this.fieldWillValidate.bind(this);
this.fieldDidValidate = this.fieldDidValidate.bind(this);
}
componentWillMount() {
this.context.form.addFieldWillValidateEventListener(this.fieldWillValidate);
this.context.form.addFieldDidValidateEventListener(this.fieldDidValidate);
}
componentWillUnmount() {
this.context.form.removeFieldWillValidateEventListener(this.fieldWillValidate);
this.context.form.removeFieldDidValidateEventListener(this.fieldDidValidate);
}
fieldWillValidate(fieldName) {
if (fieldName === this.props.name) this.setState({field: undefined});
}
fieldDidValidate(field) {
if (field.name === this.props.name) this.setState({field});
}
handle_change(e) {
var new_text = e.currentTarget.value;
this.props.on_Input_Change(e, new_text);
}
render() {
const { field } = this.state;
let className = 'adaptive_placeholder_input_container';
if (field !== undefined) {
if (field.hasErrors()) className += ' error';
if (field.hasWarnings()) className += ' warning';
}
return (
<div className={className}>
<input
type={this.props.type}
name={this.props.name}
className="adaptive_input"
required
onChange={this.handle_change.bind(this)} />
<label
className="adaptive_placeholder"
alt={this.props.initial}
placeholder={this.props.focused} />
</div>
);
}
}
class Form extends React.Component {
constructor(props) {
super(props);
this.state = {
Name: 'No Name',
Value_1: '0',
Value_2: '0',
Display_Value: '0'
};
}
...