Initial work on Login view, fixed some style issues.
So far, the basic structure of the Login view has been imported. The css properties need to be converted to use rem. The component also needs to be made functional and reactive. Planning on using property callbacks for Child -> Parent communication.
This commit is contained in:
parent
a9d6f2021d
commit
f1a7e39e13
@ -0,0 +1,4 @@
|
|||||||
|
.appWrapper {
|
||||||
|
height: calc(100vh - 22px);
|
||||||
|
background: linear-gradient(to top, rgba(0, 0, 0, 0.75) 0%, rgba(0, 0, 0, 0) 100%);
|
||||||
|
}
|
@ -8,37 +8,45 @@ import Landing from './landing/Landing';
|
|||||||
import Login from './login/Login';
|
import Login from './login/Login';
|
||||||
import Settings from './settings/Settings';
|
import Settings from './settings/Settings';
|
||||||
|
|
||||||
|
import './Application.css'
|
||||||
|
|
||||||
type ApplicationProps = {
|
type ApplicationProps = {
|
||||||
currentView: View
|
currentView: View
|
||||||
}
|
}
|
||||||
|
|
||||||
class Application extends React.Component<ApplicationProps> {
|
class Application extends React.Component<ApplicationProps> {
|
||||||
|
|
||||||
render() {
|
getViewElement(): JSX.Element {
|
||||||
switch(this.props.currentView) {
|
switch(this.props.currentView) {
|
||||||
case View.WELCOME:
|
case View.WELCOME:
|
||||||
return <>
|
return <>
|
||||||
<Frame />
|
|
||||||
<Welcome />
|
<Welcome />
|
||||||
</>
|
</>
|
||||||
case View.LANDING:
|
case View.LANDING:
|
||||||
return <>
|
return <>
|
||||||
<Frame />
|
|
||||||
<Landing />
|
<Landing />
|
||||||
</>
|
</>
|
||||||
case View.LOGIN:
|
case View.LOGIN:
|
||||||
return <>
|
return <>
|
||||||
<Frame />
|
<Login cancelable={false} />
|
||||||
<Login />
|
|
||||||
</>
|
</>
|
||||||
case View.SETTINGS:
|
case View.SETTINGS:
|
||||||
return <>
|
return <>
|
||||||
<Frame />
|
|
||||||
<Settings />
|
<Settings />
|
||||||
</>
|
</>
|
||||||
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Frame />
|
||||||
|
<div className="appWrapper">
|
||||||
|
{this.getViewElement()}
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
transition: background-color 1s ease;
|
transition: background-color 1s ease;
|
||||||
/*background-color: rgba(0, 0, 0, 0.5);*/
|
background-color: rgba(0, 0, 0, 0.5);
|
||||||
-webkit-user-select: none;
|
-webkit-user-select: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -48,6 +48,7 @@
|
|||||||
/* Frame logo (windows only). */
|
/* Frame logo (windows only). */
|
||||||
#frameTitleDock {
|
#frameTitleDock {
|
||||||
padding: 0px 10px;
|
padding: 0px 10px;
|
||||||
|
display: flex;
|
||||||
}
|
}
|
||||||
#frameTitleText {
|
#frameTitleText {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
|
423
src/renderer/components/login/Login.css
Normal file
423
src/renderer/components/login/Login.css
Normal file
@ -0,0 +1,423 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* *
|
||||||
|
* Login View (login.ejs) *
|
||||||
|
* *
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
/* Styles for dimmer login span. */
|
||||||
|
.loginSpanDim {
|
||||||
|
font-size: 12px;
|
||||||
|
color: #848484;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Main login container. */
|
||||||
|
#loginContainer {
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
transition: filter 0.25s ease;
|
||||||
|
background: rgba(0, 0, 0, 0.50);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Login cancel button styles. */
|
||||||
|
#loginCancelContainer {
|
||||||
|
position: absolute;
|
||||||
|
top: 5%;
|
||||||
|
right: 5%;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Login cancel button styles. */
|
||||||
|
#loginCancelButton {
|
||||||
|
background: none;
|
||||||
|
border: none;
|
||||||
|
outline: none;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: 0.25s ease;
|
||||||
|
}
|
||||||
|
#loginCancelButton:hover #loginCancelIcon,
|
||||||
|
#loginCancelButton:hover #loginCancelText,
|
||||||
|
#loginCancelButton:focus #loginCancelIcon,
|
||||||
|
#loginCancelButton:focus #loginCancelText {
|
||||||
|
text-shadow: 0px 0px 20px white;
|
||||||
|
}
|
||||||
|
#loginCancelButton:hover #loginCancelIcon,
|
||||||
|
#loginCancelButton:focus #loginCancelIcon {
|
||||||
|
box-shadow: 0px 0px 20px white;
|
||||||
|
}
|
||||||
|
#loginCancelButton:active #loginCancelIcon,
|
||||||
|
#loginCancelButton:active #loginCancelText {
|
||||||
|
text-shadow: 0px 0px 20px rgba(255, 255, 255, 0.75);
|
||||||
|
color: rgba(255, 255, 255, 0.75);
|
||||||
|
border-color: rgba(255, 255, 255, 0.75);
|
||||||
|
}
|
||||||
|
#loginCancelButton:active #loginCancelIcon {
|
||||||
|
box-shadow: 0px 0px 20px rgba(255, 255, 255, 0.75);
|
||||||
|
}
|
||||||
|
#loginCancelButton:disabled {
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
#loginCancelButton:disabled #loginCancelIcon,
|
||||||
|
#loginCancelButton:disabled #loginCancelText {
|
||||||
|
color: rgba(255, 255, 255, 0.75);
|
||||||
|
border-color: rgba(255, 255, 255, 0.75);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The X in a circle icon for the cancel button. */
|
||||||
|
#loginCancelIcon {
|
||||||
|
border-radius: 50%;
|
||||||
|
border: 1px solid white;
|
||||||
|
box-sizing: border-box;
|
||||||
|
height: 30px;
|
||||||
|
width: 30px;
|
||||||
|
font-size: 19px;
|
||||||
|
line-height: 30px;
|
||||||
|
margin: 0 auto;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
transition: 0.25s ease;
|
||||||
|
}
|
||||||
|
/* Text for the login cancel button. */
|
||||||
|
#loginCancelText {
|
||||||
|
font-size: 15px;
|
||||||
|
transition: 0.25s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Login content wrapper. */
|
||||||
|
#loginContent {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
height: 100%;
|
||||||
|
padding: 0px 25px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Login form. */
|
||||||
|
#loginForm {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Login form anchor styles. */
|
||||||
|
#loginForm a {
|
||||||
|
font-size: 12px;
|
||||||
|
color: #848484;
|
||||||
|
font-weight: bold;
|
||||||
|
text-decoration: none;
|
||||||
|
transition: 0.25s ease;
|
||||||
|
}
|
||||||
|
#loginForm a:hover,
|
||||||
|
#loginForm a:focus {
|
||||||
|
color: #a2a2a2;
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
#loginForm a:active {
|
||||||
|
color: #8b8b8b;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Logo on login form. */
|
||||||
|
#loginImageSeal {
|
||||||
|
border-radius: 50%;
|
||||||
|
border: 2px solid #cad7e1;
|
||||||
|
background: rgba(1, 2, 1, 0.5);
|
||||||
|
height: 125px;
|
||||||
|
width: 125px;
|
||||||
|
box-shadow: 0px 0px 10px 0px rgb(0, 0, 0);
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Header on login view. */
|
||||||
|
#loginSubheader {
|
||||||
|
font-family: 'Avenir Medium';
|
||||||
|
margin-bottom: 25px;
|
||||||
|
font-size: 12px;
|
||||||
|
letter-spacing: 1px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Add spacing between password field and options bar. */
|
||||||
|
#labelPassword {
|
||||||
|
margin-bottom: 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Container which contains the forgot and remember options. */
|
||||||
|
#loginOptions {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Remember option text. */
|
||||||
|
#loginRememberText {
|
||||||
|
padding-right: 10px;
|
||||||
|
transition: 0.25s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Login button styles. */
|
||||||
|
#loginButton {
|
||||||
|
background: none;
|
||||||
|
font-weight: bold;
|
||||||
|
letter-spacing: 2px;
|
||||||
|
border: none;
|
||||||
|
padding: 15px 5px;
|
||||||
|
margin: 10px 0px;
|
||||||
|
cursor: pointer;
|
||||||
|
position: relative;
|
||||||
|
right: -20px;
|
||||||
|
transition: 0.5s ease;
|
||||||
|
}
|
||||||
|
#loginButton:disabled {
|
||||||
|
color: rgba(255, 255, 255, 0.75);
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
#loginButton[loading] {
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
#loginButton:hover,
|
||||||
|
#loginButton:focus {
|
||||||
|
text-shadow: 0px 0px 20px #fff;
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
#loginButton:active {
|
||||||
|
color: #c7c7c7;
|
||||||
|
text-shadow: 0px 0px 20px #c7c7c7;
|
||||||
|
}
|
||||||
|
#loginSVG {
|
||||||
|
-webkit-transform: translate3d(0, 0, 0);
|
||||||
|
overflow: visible;
|
||||||
|
transform: rotate(90deg);
|
||||||
|
margin-left: 20px;
|
||||||
|
transition: 0.25s ease;
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
}
|
||||||
|
#loginButton:hover #loginSVG,
|
||||||
|
#loginButton:focus #loginSVG {
|
||||||
|
-webkit-filter: drop-shadow(0px 0px 2px #fff);
|
||||||
|
}
|
||||||
|
#loginButton:active #loginSVG .arrowLine {
|
||||||
|
stroke: #c7c7c7;
|
||||||
|
}
|
||||||
|
#loginButton:active #loginSVG {
|
||||||
|
-webkit-filter: drop-shadow(0px 0px 2px #c7c7c7);
|
||||||
|
}
|
||||||
|
#loginButton:disabled #loginSVG .arrowLine {
|
||||||
|
stroke: rgba(255, 255, 255, 0.75);
|
||||||
|
}
|
||||||
|
|
||||||
|
#loginButtonContent {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
#loginButton .circle-loader,
|
||||||
|
#loginButton[loading] #loginSVG {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
#loginButton[loading] .circle-loader,
|
||||||
|
#loginButton #loginSVG {
|
||||||
|
display: initial;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.circle-loader {
|
||||||
|
margin-left: 20px;
|
||||||
|
border: 2px solid rgba(255, 255, 255, 0.5);
|
||||||
|
border-left-color: #ffffff;
|
||||||
|
animation-name: loader-spin;
|
||||||
|
animation-duration: 1s;
|
||||||
|
animation-iteration-count: infinite;
|
||||||
|
animation-timing-function: linear;
|
||||||
|
position: relative;
|
||||||
|
display: inline-block;
|
||||||
|
vertical-align: top;
|
||||||
|
border-radius: 50%;
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
}
|
||||||
|
.load-complete {
|
||||||
|
animation: none;
|
||||||
|
border-color: #ffffff;
|
||||||
|
transition: border 500ms ease-out;
|
||||||
|
}
|
||||||
|
.checkmark {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.checkmark.draw:after {
|
||||||
|
animation-duration: 800ms;
|
||||||
|
animation-timing-function: ease;
|
||||||
|
animation-name: checkmark;
|
||||||
|
transform: scaleX(-1) rotate(135deg);
|
||||||
|
}
|
||||||
|
.checkmark:after {
|
||||||
|
opacity: 1;
|
||||||
|
height: 8px;
|
||||||
|
width: 4px;
|
||||||
|
transform-origin: left top;
|
||||||
|
border-right: 2px solid #ffffff;
|
||||||
|
border-top: 2px solid #ffffff;
|
||||||
|
content: '';
|
||||||
|
left: 2px;
|
||||||
|
top: 8px;
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
@keyframes loader-spin {
|
||||||
|
0% {
|
||||||
|
transform: rotate(0deg);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: rotate(360deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@keyframes checkmark {
|
||||||
|
0% {
|
||||||
|
height: 0;
|
||||||
|
width: 0;
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
20% {
|
||||||
|
height: 0;
|
||||||
|
width: 4px;
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
40% {
|
||||||
|
height: 8px;
|
||||||
|
width: 4px;
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
height: 8px;
|
||||||
|
width: 4px;
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*.spinningCircle {
|
||||||
|
margin-left: 20px;
|
||||||
|
height: 16px;
|
||||||
|
width: 16px;
|
||||||
|
border-radius: 50%;
|
||||||
|
border: 2px solid rgba(255,255,255,0);
|
||||||
|
border-top-color: #ffffff;
|
||||||
|
border-right-color: #ffffff;
|
||||||
|
border-left-color: rgba(255, 255, 255, 0.50);
|
||||||
|
border-bottom-color: rgba(255, 255, 255, 0.50);
|
||||||
|
animation: single2 4s infinite linear;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes single2 {
|
||||||
|
0% {
|
||||||
|
transform: rotate(0deg);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: rotate(720deg);
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
|
||||||
|
/* Disclaimer container. */
|
||||||
|
#loginDisclaimer {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Add spacing between register anchor and disclaimer. */
|
||||||
|
#loginRegisterSpan {
|
||||||
|
margin-bottom: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Disclaimer text styles. */
|
||||||
|
.loginDisclaimerText {
|
||||||
|
font-size: 7px;
|
||||||
|
color: #848484;
|
||||||
|
font-weight: bold;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* * *
|
||||||
|
* Login View | Custom Checkbox
|
||||||
|
* * */
|
||||||
|
|
||||||
|
/* Checkbox container. */
|
||||||
|
#checkmarkContainer {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
align-items: center;
|
||||||
|
position: relative;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 22px;
|
||||||
|
-webkit-user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Hide the default checkbox. */
|
||||||
|
#checkmarkContainer input {
|
||||||
|
opacity: 0;
|
||||||
|
cursor: pointer;
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Create a custom checkbox. */
|
||||||
|
.loginCheckmark {
|
||||||
|
position: relative;
|
||||||
|
height: 10px;
|
||||||
|
width: 10px;
|
||||||
|
border: 1px solid #848484;
|
||||||
|
border-radius: 1px;
|
||||||
|
background: none;
|
||||||
|
transition: 0.25s ease;
|
||||||
|
}
|
||||||
|
/* On hover and focus, add a grey border color. */
|
||||||
|
#checkmarkContainer:hover input ~ *,
|
||||||
|
#checkmarkContainer input:focus ~ * {
|
||||||
|
color: #a2a2a2;
|
||||||
|
border-color: #a2a2a2;
|
||||||
|
}
|
||||||
|
/* On keydown, darken the checkbox a bit. */
|
||||||
|
#checkmarkContainer input:active ~ *:not(#loginRememberText) {
|
||||||
|
color: #8d8d8d;
|
||||||
|
border-color: #8d8d8d;
|
||||||
|
}
|
||||||
|
#checkmarkContainer[disabled] {
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
/* For checked -> #checkmarkContainer input:checked ~ * */
|
||||||
|
/* Create the checkmark/indicator (hidden when not checked). */
|
||||||
|
.loginCheckmark:after {
|
||||||
|
content: "";
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
/* Show the checkmark when checked. */
|
||||||
|
#checkmarkContainer input:checked ~ .loginCheckmark:after {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
/* Style the checkmark/indicator. */
|
||||||
|
#checkmarkContainer .loginCheckmark:after {
|
||||||
|
position: absolute;
|
||||||
|
left: 3.5px;
|
||||||
|
top: 0.5px;
|
||||||
|
width: 2px;
|
||||||
|
height: 6px;
|
||||||
|
border: solid #a2a2a2;
|
||||||
|
border-width: 0 2px 2px 0;
|
||||||
|
transform: rotate(45deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
#login_filter {
|
||||||
|
height: calc(100% - 22px);
|
||||||
|
width: 100%;
|
||||||
|
z-index: 9000;
|
||||||
|
position: absolute;
|
||||||
|
filter: blur(8px) contrast(0.9) brightness(1.0);
|
||||||
|
background: url('./../images/backgrounds/0.jpg') no-repeat center center fixed;
|
||||||
|
transform: scale(1.2);
|
||||||
|
background-size: cover;
|
||||||
|
}
|
||||||
|
*/
|
@ -1,11 +1,81 @@
|
|||||||
import * as React from 'react'
|
import * as React from 'react'
|
||||||
|
import LoginField from './login-field/LoginField'
|
||||||
|
|
||||||
export default class Login extends React.Component {
|
import './Login.css'
|
||||||
|
|
||||||
|
type LoginProperties = {
|
||||||
|
cancelable: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class Login extends React.Component<LoginProperties> {
|
||||||
|
|
||||||
|
getCancelButton(): JSX.Element {
|
||||||
|
if(this.props.cancelable) {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div id="loginCancelContainer">
|
||||||
|
<button id="loginCancelButton">
|
||||||
|
<div id="loginCancelIcon">X</div>
|
||||||
|
<span id="loginCancelText">Cancel</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
return (<></>)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return <>
|
return (
|
||||||
LOGIN TBD
|
<>
|
||||||
|
<div id="loginContainer">
|
||||||
|
{this.getCancelButton()}
|
||||||
|
<div id="loginContent">
|
||||||
|
<form id="loginForm">
|
||||||
|
<img id="loginImageSeal" src="../images/SealCircle.png"/>
|
||||||
|
<span id="loginSubheader">MINECRAFT LOGIN</span>
|
||||||
|
|
||||||
|
<LoginField password={false} />
|
||||||
|
<LoginField password={true} />
|
||||||
|
|
||||||
|
<div id="loginOptions">
|
||||||
|
<span className="loginSpanDim">
|
||||||
|
<a href="https://my.minecraft.net/en-us/password/forgot/">forgot password?</a>
|
||||||
|
</span>
|
||||||
|
<label id="checkmarkContainer">
|
||||||
|
<input id="loginRememberOption" type="checkbox" checked></input>
|
||||||
|
<span id="loginRememberText" className="loginSpanDim">remember me?</span>
|
||||||
|
<span className="loginCheckmark"></span>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<button id="loginButton" disabled>
|
||||||
|
<div id="loginButtonContent">
|
||||||
|
LOGIN
|
||||||
|
<svg id="loginSVG" viewBox="0 0 24.87 13.97">
|
||||||
|
<defs>
|
||||||
|
<style>{'.arrowLine{transition: 0.25s ease;}'}</style> {/** TODO */}
|
||||||
|
</defs>
|
||||||
|
<polyline className="arrowLine" fill="none" stroke="#FFF" strokeWidth="2px" points="0.71 13.26 12.56 1.41 24.16 13.02"/>
|
||||||
|
</svg>
|
||||||
|
<div className="circle-loader">
|
||||||
|
<div className="checkmark draw"></div>
|
||||||
|
</div>
|
||||||
|
{/*<div className="spinningCircle" id="loginSpinner"></div>-*/}
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
<div id="loginDisclaimer">
|
||||||
|
<span className="loginSpanDim" id="loginRegisterSpan">
|
||||||
|
<a href="https://minecraft.net/en-us/store/minecraft/">Need an Account?</a>
|
||||||
|
</span>
|
||||||
|
<p className="loginDisclaimerText">Your password is sent directly to mojang and never stored.</p>
|
||||||
|
<p className="loginDisclaimerText">Helios Launcher is not affiliated with Mojang AB.</p>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</>
|
</>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
85
src/renderer/components/login/login-field/LoginField.css
Normal file
85
src/renderer/components/login/login-field/LoginField.css
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
/* Container to organize login field elements. */
|
||||||
|
.loginFieldContainer {
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* SVG icons on the login view. */
|
||||||
|
.loginSVG {
|
||||||
|
fill: #fff;
|
||||||
|
height: 20px;
|
||||||
|
width: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Span which displays errors related to login field content. */
|
||||||
|
.loginErrorSpan {
|
||||||
|
font-family: 'Avenir Medium';
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 8px;
|
||||||
|
color: #ff1b0c;
|
||||||
|
width: 100%;
|
||||||
|
text-align: right;
|
||||||
|
position: absolute;
|
||||||
|
top: 7px;
|
||||||
|
opacity: 0;
|
||||||
|
transition: 0.25s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.shake {
|
||||||
|
animation: shake 0.82s cubic-bezier(.36,.07,.19,.97) both;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes shake {
|
||||||
|
10%, 90% {
|
||||||
|
transform: translate3d(-1px, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
20%, 80% {
|
||||||
|
transform: translate3d(2px, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
30%, 50%, 70% {
|
||||||
|
transform: translate3d(-4px, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
40%, 60% {
|
||||||
|
transform: translate3d(4px, 0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Login text input styles. */
|
||||||
|
.loginField {
|
||||||
|
font-family: 'Avenir Book';
|
||||||
|
background: none;
|
||||||
|
border-width: 1.5px 0px 0px 0px;
|
||||||
|
border-style: solid;
|
||||||
|
width: 250px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
border-color: #fff;
|
||||||
|
color: rgba(255, 255, 255, 0.75);
|
||||||
|
font-weight: bold;
|
||||||
|
text-align: center;
|
||||||
|
box-sizing: border-box;
|
||||||
|
padding: 7.5px;
|
||||||
|
font-size: 10px;
|
||||||
|
letter-spacing: 1px;
|
||||||
|
}
|
||||||
|
.loginField:focus {
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
.loginField:disabled {
|
||||||
|
color: rgba(255, 255, 255, 0.50);
|
||||||
|
}
|
||||||
|
.loginField::-webkit-input-placeholder {
|
||||||
|
color: rgba(255, 255, 255, 0.75);
|
||||||
|
font-size: 10px;
|
||||||
|
letter-spacing: 1px;
|
||||||
|
text-align: center;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
.loginField:focus::-webkit-input-placeholder {
|
||||||
|
color: transparent;
|
||||||
|
}
|
68
src/renderer/components/login/login-field/LoginField.tsx
Normal file
68
src/renderer/components/login/login-field/LoginField.tsx
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
import * as React from 'react'
|
||||||
|
|
||||||
|
import './LoginField.css'
|
||||||
|
|
||||||
|
type LoginFieldProps = {
|
||||||
|
password: boolean,
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class LoginField extends React.Component<LoginFieldProps> {
|
||||||
|
|
||||||
|
getFieldSvg(): JSX.Element {
|
||||||
|
if(this.props.password) {
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<svg className="loginSVG" viewBox="40 32 60.36 70.43">
|
||||||
|
<g>
|
||||||
|
<path d="M86.16,54a16.38,16.38,0,1,0-32,0H44V102.7H96V54Zm-25.9-3.39a9.89,9.89,0,1,1,19.77,0A9.78,9.78,0,0,1,79.39,54H60.89A9.78,9.78,0,0,1,60.26,50.59ZM70,96.2a6.5,6.5,0,0,1-6.5-6.5,6.39,6.39,0,0,1,3.1-5.4V67h6.5V84.11a6.42,6.42,0,0,1,3.39,5.6A6.5,6.5,0,0,1,70,96.2Z"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<svg className="loginSVG" viewBox="40 37 65.36 61.43">
|
||||||
|
<g>
|
||||||
|
<path d="M86.77,58.12A13.79,13.79,0,1,0,73,71.91,13.79,13.79,0,0,0,86.77,58.12M97,103.67a3.41,3.41,0,0,0,3.39-3.84,27.57,27.57,0,0,0-54.61,0,3.41,3.41,0,0,0,3.39,3.84Z"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getDefaultErrorMessage(): string {
|
||||||
|
if(this.props.password) {
|
||||||
|
return '* Required'
|
||||||
|
} else {
|
||||||
|
return '* Invalid Value'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getPlaceholder(): string {
|
||||||
|
if(this.props.password) {
|
||||||
|
return 'PASSWORD'
|
||||||
|
} else {
|
||||||
|
return 'EMAIL OR USERNAME'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div className="loginFieldContainer">
|
||||||
|
{this.getFieldSvg()}
|
||||||
|
<span className="loginErrorSpan">{this.getDefaultErrorMessage()}</span>
|
||||||
|
<input className="loginField" type={this.props.password ? 'password' : 'text'} placeholder={this.getPlaceholder()}/>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -25,6 +25,20 @@
|
|||||||
* *
|
* *
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
|
/* TODO: Temp for development */
|
||||||
|
body {
|
||||||
|
background-image: url('../../assets/images/backgrounds/3.jpg');
|
||||||
|
background-size: cover;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set height to 100% */
|
||||||
|
html {
|
||||||
|
min-height: 100%;
|
||||||
|
}
|
||||||
|
body {
|
||||||
|
height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
/* Reset body, html, and div presets. */
|
/* Reset body, html, and div presets. */
|
||||||
body, html, div {
|
body, html, div {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
@ -2,7 +2,7 @@ import { Reducer } from 'redux'
|
|||||||
import { View } from '../../meta/Views'
|
import { View } from '../../meta/Views'
|
||||||
import { ChangeViewAction, ViewActionType } from '../actions/viewActions'
|
import { ChangeViewAction, ViewActionType } from '../actions/viewActions'
|
||||||
|
|
||||||
const defaultView = View.WELCOME
|
const defaultView = View.LOGIN
|
||||||
|
|
||||||
const ViewReducer: Reducer<View, ChangeViewAction> = (state = defaultView, action) => {
|
const ViewReducer: Reducer<View, ChangeViewAction> = (state = defaultView, action) => {
|
||||||
switch(action.type) {
|
switch(action.type) {
|
||||||
|
Loading…
Reference in New Issue
Block a user