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" /> |