Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save GQAdonis/92c60d7fe02111ea22af to your computer and use it in GitHub Desktop.
Save GQAdonis/92c60d7fe02111ea22af to your computer and use it in GitHub Desktop.
Material Compact Login Animation With React
<div id="mount"/>
//Based on http://codepen.io/yusufbkr/pen/RPBQqg/
//Using React and GSAP tohether with react-gsap-enhancer
//Check out here for the API and mode demos:
//https://github.com/azazdeaz/react-gsap-enhancer
function appearAnim({target}) {
return TweenMax.from(target, 0.53, {
delay: 1,
y: -34,
opacity: 0,
scale: 0.82,
ease: Back.easeOut
})
}
function switchAnim({target}) {
const shape = target.find({className: 'shape'})
const box = target.find({className: 'box'})
const registerContent = target
.find({className: 'register-content'})
.findAllInChildren()
const switchButton = target.find({name: 'switch'})
return new TimelineMax()
.pause()
.add('login')
.to(switchButton, 0.3, {
left: '160px',
top: '160px',
ease: Sine.easeInOut,
}, 'login')
.add('middle')
.to(switchButton, 0.4, {
left: '0px',
width: '100%',
height: '100%',
top: '0',
borderRadius: '10px',
ease: Sine.easeInOut,
})
.to(box, 0.4, {
scale: 0.94,
y: '-=29',
ease: Sine.easeInOut,
}, 'middle')
.staggerFromTo(registerContent, 0.32, {scale: 0.95}, {scale: 1, autoAlpha: 1}, 0.032)
.to(shape, 0.55, {
xPercent: 43,
yPercent: -43,
rotation: 45,
ease: Sine.easeInOut,
}, 'middle')
.add('register')
}
@ReactGSAPEnhancer.default()
class Login extends React.Component {
constructor(props) {
super(props)
this.state = {register: false}
}
renderInput(label, name, type) {
return <div className="input">
<label for={name}>{label}</label>
<input type={type} name={name} id={name}/>
<span className="spin"/>
</div>
}
handleOpenClick = (label) => {
this.setState({register: !this.state.register})
}
componentDidMount() {
this.addAnimation(appearAnim)
this.switchAnim = this.addAnimation(switchAnim)
}
componentDidUpdate() {
this.switchAnim.tweenTo(this.state.register ? 'register' : 'login')
}
render() {
return <div className="materialContainer">
<div className="box">
<div className="title">LOGIN</div>
{this.renderInput('Username', 'name', 'text')}
{this.renderInput('Password', 'pass', 'password')}
<div className="button login">
<button><span>GO</span> <i className="fa fa-check"></i></button>
</div>
<a href="" className="pass-forgot">Forgot your password?</a>
</div>
<div className="overbox">
<div name="switch" className="material-button alt-2" onClick={this.handleOpenClick}>
<span className="shape"/>
</div>
<div className="register-content">
<div className="title">REGISTER</div>
{this.renderInput('Username', 'regname', 'text')}
{this.renderInput('Password', 'regpass', 'password')}
{this.renderInput('Repeat Password', 'reregpass', 'password')}
<div className="button">
<button><span>NEXT</span></button>
</div>
</div>
</div>
</div>
}
}
ReactDOM.render(<Login/>, document.querySelector('#mount'))
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.14.3/react.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.14.3/react-dom.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/gsap/1.16.1/TweenMax.min.js"></script>
<script src="https://rawgit.com/azazdeaz/react-gsap-enhancer/7a08a6570618a678052d20d9d5bc26384fc422b2/react-gsap-enhancer.js"></script>
.box {
position: relative;
top: 0;
opacity: 1;
float: left;
padding: 60px 50px 40px 50px;
width: 100%;
background: #fff;
border-radius: 10px;
transform: scale(1);
z-index: 5;
}
.box.back {
transform: scale(.95);
top: -20px;
opacity: .8;
z-index: -1;
}
.box:before {
content: "";
width: 100%;
height: 30px;
border-radius: 10px;
position: absolute;
top: -10px;
background: rgba(255, 255, 255, .6);
left: 0;
transform: scale(.95);
z-index: -1;
}
.overbox .title {
color: #fff;
}
.overbox .title:before {
background: #fff;
}
.title {
width: 100%;
float: left;
line-height: 46px;
font-size: 34px;
font-weight: 700;
letter-spacing: 2px;
color: #ED2553;
position: relative;
}
.title:before {
content: "";
width: 5px;
height: 100%;
position: absolute;
top: 0;
left: -50px;
background: #ED2553;
}
.input,
.input label,
.input input,
.input .spin,
.button,
.button button {
width: 100%;
float: left;
}
.input,
.button {
margin-top: 30px;
height: 70px;
}
.input,
.input input,
.button,
.button button {
position: relative;
}
.input input {
height: 60px;
top: 10px;
border: none;
background: transparent;
}
.input input,
.input label,
.button button {
font-family: 'Roboto', sans-serif;
font-size: 24px;
color: rgba(0, 0, 0, 0.8);
font-weight: 300;
}
.input:before,
.input .spin {
width: 100%;
height: 1px;
position: absolute;
bottom: 0;
left: 0;
}
.input:before {
content: "";
background: rgba(0, 0, 0, 0.1);
z-index: 3;
}
.input .spin {
background: #ED2553;
z-index: 4;
width: 0;
}
.overbox .input .spin {
background: rgba(255, 255, 255, 1);
}
.overbox .input:before {
background: rgba(255, 255, 255, 0.5);
}
.input label {
position: absolute;
top: 10px;
left: 0;
z-index: 2;
cursor: pointer;
line-height: 60px;
}
.button.login {
width: 60%;
left: 20%;
}
.button.login button,
.button button {
width: 100%;
line-height: 64px;
left: 0%;
background-color: transparent;
border: 3px solid rgba(0, 0, 0, 0.1);
font-weight: 900;
font-size: 18px;
color: rgba(0, 0, 0, 0.2);
}
.button.login {
margin-top: 30px;
}
.button {
margin-top: 20px;
}
.button button {
background-color: #fff;
color: #ED2553;
border: none;
}
.button.login button.active {
border: 3px solid transparent;
color: #fff !important;
}
.button.login button.active span {
opacity: 0;
transform: scale(0);
}
.button.login button.active i.fa {
opacity: 1;
transform: scale(1) rotate(-0deg);
}
.button.login button i.fa {
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
line-height: 60px;
transform: scale(0) rotate(-45deg);
}
.button.login button:hover {
color: #ED2553;
border-color: #ED2553;
}
.button {
margin: 40px 0;
overflow: hidden;
z-index: 2;
}
.button button {
cursor: pointer;
position: relative;
z-index: 2;
}
.pass-forgot {
width: 100%;
float: left;
text-align: center;
color: rgba(0, 0, 0, 0.4);
font-size: 18px;
}
.click-efect {
position: absolute;
top: 0;
left: 0;
background: #ED2553;
border-radius: 50%;
}
.overbox {
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
overflow: inherit;
border-radius: 10px;
padding: 60px 50px 40px 50px;
}
.overbox .title,
.overbox .button,
.overbox .input {
z-index: 111;
position: relative;
color: #fff !important;
}
.register-content > * {
opacity: 0;
visibility: 0;
}
.overbox .title {
width: 80%;
}
.overbox .input {
margin-top: 20px;
}
.overbox .input input,
.overbox .input label {
color: #fff;
}
.overbox .material-button,
.overbox .material-button .shape,
.overbox .alt-2,
.overbox .alt-2 .shape {
display: block;
}
.material-button,
.alt-2 {
width: 140px;
height: 140px;
border-radius: 50%;
background: #ED2553;
position: absolute;
top: 40px;
right: -70px;
cursor: pointer;
z-index: 100;
transform: translate(0%, 0%);
}
.material-button .shape,
.alt-2 .shape {
position: absolute;
top: 0;
right: 0;
width: 100%;
height: 100%;
}
.material-button .shape:before,
.alt-2 .shape:before,
.material-button .shape:after,
.alt-2 .shape:after {
content: "";
background: #fff;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%) rotate(360deg);
}
.material-button .shape:before,
.alt-2 .shape:before {
width: 25px;
height: 4px;
}
.material-button .shape:after,
.alt-2 .shape:after {
height: 25px;
width: 4px;
}
.material-button.active,
.alt-2.active {
top: 50%;
right: 50%;
transform: translate(50%, -50%) rotate(0deg);
}
body {
background-image: url(https://lh4.googleusercontent.com/-XplyTa1Za-I/VMSgIyAYkHI/AAAAAAAADxM/oL-rD6VP4ts/w1184-h666/Android-Lollipop-wallpapers-Google-Now-Wallpaper-2.png);
background-position: center;
background-size: cover;
background-repeat: no-repeat;
min-height: 100vh;
font-family: 'Roboto', sans-serif;
}
body,
html {
overflow: hidden;
}
.materialContainer {
width: 100%;
max-width: 460px;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
*,
*:after,
*::before {
box-sizing: border-box;
margin: 0;
padding: 0;
text-decoration: none;
list-style-type: none;
outline: none;
}
<link href="//maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css" rel="stylesheet" />
<link href="//fonts.googleapis.com/css?family=Roboto:400,100,300,500,700,900&subset=latin,latin-ext" rel="stylesheet" />
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment