@keyframes blink {
to {
visibility: hidden;
}
}
* {
box-sizing: border-box;
}
body {
background: #282A36;
font-family: Abel;
color: white;
text-align: center;
font-size: 140%;
margin: 0;
padding: 0;
overflow: hidden;
}
h3 {
text-transform: uppercase;
font-weight: normal;
border-bottom: 2px solid rgba(0, 0, 0, 0.5);
max-width: 30rem;
margin: 0 auto 1.3em;
color: #E22B56;
font-size: 2em;
}
.blink {
display: inline-block;
border-left: 2px solid #466ACE;
animation: blink 1.5s steps(5, start) infinite;
}
body, html, .grid {
height: 100%;
}
.grid {
display: table;
width: 100%;
height: 100%;
}
.col {
display: table-cell;
vertical-align: middle;
padding: 10px;
}
form {
max-width: 400px;
position: relative;
margin: 0 auto;
}
.next, .button.-submit {
position: absolute;
top: 0;
right: 0;
bottom: 0;
z-index: 2;
cursor: pointer;
}
.next {
padding: 2%;
}
.button {
background: #466ACE;
color: white;
border: 0;
padding: .8em 1em;
margin: 0;
border-radius: 4px;
font-weight: bold;
cursor: pointer;
}
.button.-submit {
border-radius: 0 4px 4px 0;
}
a.button {
display: inline-block;
}
.button:hover, .button:focus {
opacity: 0.9;
outline: 0;
}
.next svg {
fill: #466ACE;
width: 40px;
height: 40px;
position: absolute;
top: 50%;
right: 0;
margin: -20px 0 0;
}
.group {
background: white;
position: absolute;
opacity: 0;
top: 200px;
left: 0;
right: 0;
z-index: 10;
width: 100%;
transition: all 0.3s;
text-align: left;
border-radius: 4px;
transform: scale(0);
}
.group.active {
opacity: 1;
top: 0;
transform: scale(1);
}
.group.done.weight1 {
top: -20px;
opacity: .8;
z-index: 1;
transform: scale(.9, .9);
}
.group.done.weight2 {
top: -40px;
opacity: .6;
z-index: 1;
transform: scale(.8, .8);
}
.group.done.weight3 {
top: -60px;
opacity: .4;
z-index: 1;
transform: scale(.7, .7);
}
input {
border: 0;
margin: 0;
padding: 20px 15px;
width: 100%;
font-size: 1em;
background: transparent;
border-width: 2px;
border-style: solid;
border-color: transparent;
border-radius: 4px;
}
input:focus {
outline: 0;
border-color: #E22B56;
}
label {
display: block;
position: absolute;
top: 30%;
left: 15px;
color: #999;
width: 90%;
cursor: text;
transform-origin: 0 0;
transition: all 0.3s;
}
label.focus {
top: 4px;
left: 15px;
transform: scale(.5);
}
class Field extends React.Component {
constructor() {
super()
this.state = {
focus: false,
}
}
componentDidMount() {
if ( this.props.focus )
this.setState({focus: true })
}
onBlur() {
const { value, onLeave } = this.props
if ( value && onLeave ) onLeave()
this.setState({ focus: true })
}
onFocus() {
this.props.onFocus()
this.setState({ focus: true })
}
onChange(e) {
this.props.onChange(e.target.value)
}
handleKeyUp(e) {
switch (e.key) {
case 'Enter':
this.onBlur()
break
}
}
render() {
return <div className="field">
<label htmlFor={this.props.id} className={ this.props.value ? "focus" : ""}>{ this.props.label }</label>
<input
id={this.props.id}
type="text"
value={this.props.value}
onChange={ (e) => this.onChange(e) }
onFocus={ () => this.onFocus() }
on_Blur={ () => this.onBlur() }
onClick={ () => this.onFocus() }
onKeyUp={ (e) => this.handleKeyUp(e) }
/>
</div>
}
}
class Next extends React.Component {
render() {
return (
<div className="next">
<svg viewBox="0 0 20 20" enable-background="new 0 0 20 20">
<path d="M9.163,4.516c0.418,0.408,4.502,4.695,4.502,4.695C13.888,9.43,14,9.715,14,10s-0.112,0.57-0.335,0.787
c0,0-4.084,4.289-4.502,4.695c-0.418,0.408-1.17,0.436-1.615,0c-0.446-0.434-0.481-1.041,0-1.574L11.295,10L7.548,6.092
c-0.481-0.533-0.446-1.141,0-1.576C7.993,4.08,8.745,4.107,9.163,4.516z"/>
</svg>
</div>
)
}
}
class Group extends React.Component {
render() {
const { active, done, doneWeight, hide } = this.props
let classNames = ["group"]
if ( active ) classNames.push("active")
if ( done ) classNames.push("done")
if ( doneWeight ) classNames.push(`weight${this.props.doneWeight}`)
if ( hide ) return null
return (
<div className={ classNames.join(" ") }>
{ this.props.children }
</div>
)
}
}
class Form extends React.Component {
constructor() {
super()
this.state = {
activeField: 1,
}
}
clear() {
this.setState({
activeField: 1,
name: undefined,
email: undefined,
company: undefined
})
}
goToField(num) {
this.setState({ activeField: num })
}
submit(e) {
e.preventDefault()
const { email, name, company } = this.state
if ( email && name && company ) {
this.goToField(4)
} else {
}
}
render() {
const { activeField, email, name, company } = this.state
if ( activeField === 4 ) {
return (
<div>
<h2>Thanks!</h2>
<p>
<a onClick={() => this.clear()} className="button">
Start Over
</a>
</p>
</div>
)
}
return (
<div className="form">
<h3>
Contact Us
</h3>
<form onSubmit={(e) => this.submit(e) }>
<Group
active={ activeField === 1 }
done={ activeField > 1 }
doneWeight={ activeField - 1 }
hide={ activeField === 4 }
>
<Field
value={email}
label="Email"
id="email"
onChange={ (value) => this.setState({ email: value }) }
onFocus={ () => this.goToField(1) }
onLeave={ () => this.goToField(2) }
/>
{ email && <Next onClick={ () => this.goToField(2) } /> }
</Group>
<Group
active={ activeField === 2 }
done={ activeField > 2 }
doneWeight={ activeField - 2 }
hide={ activeField === 4 }
>
<Field
value={name}
label="Name"
id="name"
onChange={ (value) => this.setState({ name: value }) }
onFocus={ () => this.goToField(2) }
onLeave={ () => this.goToField(3) }
/>
{ name && <Next onClick={ () => this.goToField(3) } /> }
</Group>
<Group
active={ activeField === 3 }
done={ activeField > 3 }
doneWeight={ activeField - 3 }
hide={ activeField === 4 }
>
<Field
value={company}
id="company"
label="Company"
onChange={ (value) => this.setState({ company: value }) }
onFocus={ () => this.goToField(3) }
/>
<button className="button -submit" type="submit">SUBMIT</button>
</Group>
</form>
</div>
)
}
}
React.render(<Form />, document.getElementById('app'));
View Compiled