Remix of Yusuf Bakır's Pen Material Compact Login Animation.
Using React and GSAP tohether with react-gsap-enhancer
A Pen by Polgar Andras on CodePen.
<div id="mount"/> |
Remix of Yusuf Bakır's Pen Material Compact Login Animation.
Using React and GSAP tohether with react-gsap-enhancer
A Pen by Polgar Andras on CodePen.
//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" /> |