summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rwxr-xr-xapp/assets/images/icon-arrow-active.svg7
-rwxr-xr-xapp/assets/images/icon-arrow-inactive.svg7
-rw-r--r--app/components/Login.css49
-rw-r--r--app/components/Login.js59
4 files changed, 110 insertions, 12 deletions
diff --git a/app/assets/images/icon-arrow-active.svg b/app/assets/images/icon-arrow-active.svg
new file mode 100755
index 0000000000..9e5674866f
--- /dev/null
+++ b/app/assets/images/icon-arrow-active.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg width="24px" height="16px" viewBox="0 0 24 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+ <title>icon-arrow</title>
+ <desc>Mullvad VPN app</desc>
+ <defs></defs>
+ <path fill="#294D73" d="M18.7015867,9 L14.4331381,12.762659 C13.851665,13.2752305 13.8579999,14.1003943 14.4392669,14.612784 C15.0245863,15.1287461 15.9602099,15.1275926 16.5380921,14.6181865 L23.5668627,8.42228969 C23.8565791,8.16690324 24.000373,7.83391619 23.999837,7.50067932 L24,7.4966702 C23.999589,7.16348359 23.8547954,6.83138119 23.5668627,6.57756713 L16.5380921,0.381670278 C15.956619,-0.130901228 15.0205338,-0.125317014 14.4392669,0.387072772 C13.8539474,0.903034846 13.8552559,1.72779176 14.4331381,2.23719784 L18.7017491,6 L1.50909424,6 C0.66354084,6 0,6.67157288 0,7.5 C0,8.33420277 0.675644504,9 1.50909424,9 L18.7015867,9 Z" id="icon-arrow"></path>
+</svg> \ No newline at end of file
diff --git a/app/assets/images/icon-arrow-inactive.svg b/app/assets/images/icon-arrow-inactive.svg
new file mode 100755
index 0000000000..69c7339bc0
--- /dev/null
+++ b/app/assets/images/icon-arrow-inactive.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg width="24px" height="16px" viewBox="0 0 24 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+ <title>icon-arrow</title>
+ <desc>Mullvad VPN app</desc>
+ <defs></defs>
+ <path fill="rgba(41,77,115,0.2)" d="M18.7015867,9 L14.4331381,12.762659 C13.851665,13.2752305 13.8579999,14.1003943 14.4392669,14.612784 C15.0245863,15.1287461 15.9602099,15.1275926 16.5380921,14.6181865 L23.5668627,8.42228969 C23.8565791,8.16690324 24.000373,7.83391619 23.999837,7.50067932 L24,7.4966702 C23.999589,7.16348359 23.8547954,6.83138119 23.5668627,6.57756713 L16.5380921,0.381670278 C15.956619,-0.130901228 15.0205338,-0.125317014 14.4392669,0.387072772 C13.8539474,0.903034846 13.8552559,1.72779176 14.4331381,2.23719784 L18.7017491,6 L1.50909424,6 C0.66354084,6 0,6.67157288 0,7.5 C0,8.33420277 0.675644504,9 1.50909424,9 L18.7015867,9 Z" id="icon-arrow"></path>
+</svg> \ No newline at end of file
diff --git a/app/components/Login.css b/app/components/Login.css
index 3b46310078..9417dc5537 100644
--- a/app/components/Login.css
+++ b/app/components/Login.css
@@ -72,13 +72,21 @@
.login-form__input-wrap {
border: 4px solid rgba(0,0,0,0.1);
+ background-color: #FFFFFF;
+ background-clip: content-box;
border-radius: 8px;
margin-left: -4px;
margin-right: -4px;
+ display: flex;
+ flex-direction: row;
+ transform: 0.3s all;
+}
+.login-form__input-wrap--inactive {
+ opacity: 0.6;
}
.login-form__input-field::-webkit-input-placeholder {
- color: rgba(41,77,115,0.2);
+ color: rgba(41,77,115,0.4);
}
.login-form__fields--invisible {
@@ -89,16 +97,43 @@
width: 100%;
border-radius: 8px;
border: 0;
- padding: 5px 16px;
+ padding: 10px 12px 12px 16px;
font-family: DINPro;
- font-size: 32px;
- font-weight: bold;
- line-height: 40px;
+ font-size: 20px;
+ font-weight: 900;
+ line-height: 26px;
letter-spacing: 1px;
color: #294D73;
- background-color: #FFFFFF;
+ background-color: transparent;
+ flex: 1 1 auto;
+ transition: 0.3s all;
+}
+
+.login-form__input-field--inactive {
+ background-color: rgba(255,255,255,0.6);
}
.login-form__input-field--error {
color: #D0021B;
-} \ No newline at end of file
+}
+
+.login-form__submit {
+ flex: 0 0 auto;
+ border: 0;
+ width: 48px;
+ background-color: transparent;
+ background-image: url(../assets/images/icon-arrow-inactive.svg);
+ background-position: center;
+ background-repeat: no-repeat;
+ transition: 0.3s all;
+}
+
+.login-form__submit--active {
+ background-color: rgba(41,77,115,0.2);
+ background-image: url(../assets/images/icon-arrow-active.svg);
+}
+
+.login-form__submit--invisible {
+ visibility: hidden;
+ opacity: 0;
+}
diff --git a/app/components/Login.js b/app/components/Login.js
index 47a127c128..062510be00 100644
--- a/app/components/Login.js
+++ b/app/components/Login.js
@@ -83,6 +83,51 @@ export default class Login extends Component {
}
}
+ inputWrapClass(user) {
+ const classes = ['login-form__input-wrap'];
+
+ if(user.status === LoginState.connecting) {
+ classes.push('login-form__input-wrap--inactive');
+ }
+
+ return classes.join(' ');
+ }
+
+ inputClass(user) {
+ const map = {
+ [LoginState.failed]: 'login-form__input-field--error'
+ };
+ const classes = ['login-form__input-field'];
+ const extra = map[user.status];
+
+ return classes.concat(extra ? extra : []).join(' ');
+ }
+
+ footerClass(user) {
+ const map = {
+ [LoginState.ok]: 'login-footer--invisible',
+ [LoginState.connecting]: 'login-footer--invisible'
+ };
+ const classes = ['login-footer'];
+ const extra = map[user.status];
+
+ return classes.concat(extra ? extra : []).join(' ');
+ }
+
+ submitClass(user) {
+ const classes = ['login-form__submit'];
+
+ if(user.account.length > 0) {
+ classes.push('login-form__submit--active');
+ }
+
+ if(user.status === LoginState.connecting) {
+ classes.push('login-form__submit--invisible');
+ }
+
+ return classes.join(' ');
+ }
+
render() {
const { account, status, error } = this.props.user;
const title = this.formTitle(status);
@@ -91,9 +136,12 @@ export default class Login extends Component {
const isConnecting = status === LoginState.connecting;
const isFailed = status === LoginState.failed;
const isLoggedIn = status === LoginState.ok;
- const inputClass = ['login-form__input-field', isFailed ? 'login-form__input-field--error' : ''].join(' ');
- const footerClass = ['login-footer', (isConnecting || isLoggedIn) ? 'login-footer--invisible' : ''].join(' ');
-
+
+ const inputWrapClass = this.inputWrapClass(this.props.user);
+ const inputClass = this.inputClass(this.props.user);
+ const footerClass = this.footerClass(this.props.user);
+ const submitClass = this.submitClass(this.props.user);
+
const autoFocusRef = input => {
if(isFailed && input) {
input.focus();
@@ -136,16 +184,17 @@ export default class Login extends Component {
<div className="login-form__title">{ title }</div>
<div className={ 'login-form__fields' + (isLoggedIn ? ' login-form__fields--invisible' : '') }>
<div className="login-form__subtitle">{ subtitle }</div>
- <div className="login-form__input-wrap">
+ <div className={ inputWrapClass }>
<input className={ inputClass }
type="text"
- placeholder="0000 0000 0000"
+ placeholder="e.g 0000 0000 0000"
onChange={ ::this.handleInputChange }
onKeyUp={ ::this.handleInputKeyUp }
value={ displayAccount }
disabled={ isConnecting }
autoFocus={ true }
ref={ autoFocusRef } />
+ <button className={ submitClass } onClick={ ::this.handleLogin }></button>
</div>
</div>