Login signup zazz (#11957)
This PR re-styles the login and create account modals.
This commit is contained in:
parent
50c3cc7d75
commit
4580595bd8
|
@ -21,4 +21,4 @@
|
|||
label="admin.user_fields.create"
|
||||
icon="plus"}}
|
||||
|
||||
</div>
|
||||
</div>
|
|
@ -4,6 +4,23 @@ import cookie from "discourse/lib/cookie";
|
|||
export default Component.extend({
|
||||
classNames: ["create-account"],
|
||||
|
||||
userInputFocus(event) {
|
||||
let label = event.target.parentElement.previousElementSibling;
|
||||
if (!label.classList.contains("value-entered")) {
|
||||
label.classList.toggle("value-entered");
|
||||
}
|
||||
},
|
||||
|
||||
userInputFocusOut(event) {
|
||||
let label = event.target.parentElement.previousElementSibling;
|
||||
if (
|
||||
event.target.value.length === 0 &&
|
||||
label.classList.contains("value-entered")
|
||||
) {
|
||||
label.classList.toggle("value-entered");
|
||||
}
|
||||
},
|
||||
|
||||
didInsertElement() {
|
||||
this._super(...arguments);
|
||||
|
||||
|
@ -11,6 +28,21 @@ export default Component.extend({
|
|||
this.set("email", cookie("email"));
|
||||
}
|
||||
|
||||
let userTextFields = document.getElementsByClassName("user-fields")[0];
|
||||
|
||||
if (userTextFields) {
|
||||
userTextFields = userTextFields.getElementsByClassName(
|
||||
"ember-text-field"
|
||||
);
|
||||
}
|
||||
|
||||
if (userTextFields) {
|
||||
for (let element of userTextFields) {
|
||||
element.addEventListener("focus", this.userInputFocus);
|
||||
element.addEventListener("focusout", this.userInputFocusOut);
|
||||
}
|
||||
}
|
||||
|
||||
$(this.element).on("keydown.discourse-create-account", (e) => {
|
||||
if (!this.disabled && e.keyCode === 13) {
|
||||
e.preventDefault();
|
||||
|
@ -36,5 +68,20 @@ export default Component.extend({
|
|||
|
||||
$(this.element).off("keydown.discourse-create-account");
|
||||
$(this.element).off("click.dropdown-user-field-label");
|
||||
|
||||
let userTextFields = document.getElementsByClassName("user-fields")[0];
|
||||
|
||||
if (userTextFields) {
|
||||
userTextFields = userTextFields.getElementsByClassName(
|
||||
"ember-text-field"
|
||||
);
|
||||
}
|
||||
|
||||
if (userTextFields) {
|
||||
for (let element of userTextFields) {
|
||||
element.removeEventListener("focus", this.userInputFocus);
|
||||
element.removeEventListener("focusout", this.userInputFocusOut);
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
|
|
|
@ -22,6 +22,7 @@ import { isEmpty } from "@ember/utils";
|
|||
import { notEmpty } from "@ember/object/computed";
|
||||
import { setting } from "discourse/lib/computed";
|
||||
import { userPath } from "discourse/lib/url";
|
||||
import { helperContext } from "discourse-common/lib/helpers";
|
||||
|
||||
export default Controller.extend(
|
||||
ModalFunctionality,
|
||||
|
@ -77,6 +78,15 @@ export default Controller.extend(
|
|||
return false;
|
||||
},
|
||||
|
||||
@discourseComputed()
|
||||
wavingHandURL() {
|
||||
const emojiSet = helperContext().siteSettings.emoji_set;
|
||||
|
||||
// random number between 2 -6 to render multiple skin tone waving hands
|
||||
const random = Math.floor(Math.random() * (7 - 2) + 2);
|
||||
return getURL(`/images/emoji/${emojiSet}/wave/${random}.png`);
|
||||
},
|
||||
|
||||
@discourseComputed("userFields", "hasAtLeastOneLoginButton")
|
||||
modalBodyClasses(userFields, hasAtLeastOneLoginButton) {
|
||||
const classes = [];
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import Controller, { inject as controller } from "@ember/controller";
|
||||
import { alias, or, readOnly } from "@ember/object/computed";
|
||||
import { alias, not, or, readOnly } from "@ember/object/computed";
|
||||
import { areCookiesEnabled, escapeExpression } from "discourse/lib/utilities";
|
||||
import cookie, { removeCookie } from "discourse/lib/cookie";
|
||||
import { next, schedule } from "@ember/runloop";
|
||||
|
@ -18,6 +18,7 @@ import { getWebauthnCredential } from "discourse/lib/webauthn";
|
|||
import { isEmpty } from "@ember/utils";
|
||||
import { setting } from "discourse/lib/computed";
|
||||
import showModal from "discourse/lib/show-modal";
|
||||
import { helperContext } from "discourse-common/lib/helpers";
|
||||
|
||||
// This is happening outside of the app via popup
|
||||
const AuthErrors = [
|
||||
|
@ -45,6 +46,8 @@ export default Controller.extend(ModalFunctionality, {
|
|||
loginRequired: alias("application.loginRequired"),
|
||||
secondFactorMethod: SECOND_FACTOR_METHODS.TOTP,
|
||||
|
||||
noLoginLocal: not("canLoginLocal"),
|
||||
|
||||
resetForm() {
|
||||
this.setProperties({
|
||||
loggingIn: false,
|
||||
|
@ -62,20 +65,42 @@ export default Controller.extend(ModalFunctionality, {
|
|||
return showSecondFactor || showSecurityKey ? "hidden" : "";
|
||||
},
|
||||
|
||||
@discourseComputed()
|
||||
wavingHandURL() {
|
||||
const emojiSet = helperContext().siteSettings.emoji_set;
|
||||
|
||||
// random number between 2 -6 to render multiple skin tone waving hands
|
||||
const random = Math.floor(Math.random() * (7 - 2) + 2);
|
||||
return getURL(`/images/emoji/${emojiSet}/wave/${random}.png`);
|
||||
},
|
||||
|
||||
@discourseComputed("showSecondFactor", "showSecurityKey")
|
||||
secondFactorClass(showSecondFactor, showSecurityKey) {
|
||||
return showSecondFactor || showSecurityKey ? "" : "hidden";
|
||||
},
|
||||
|
||||
@discourseComputed("awaitingApproval", "hasAtLeastOneLoginButton")
|
||||
modalBodyClasses(awaitingApproval, hasAtLeastOneLoginButton) {
|
||||
@discourseComputed(
|
||||
"awaitingApproval",
|
||||
"hasAtLeastOneLoginButton",
|
||||
"showSecondFactor",
|
||||
"canLoginLocal"
|
||||
)
|
||||
modalBodyClasses(
|
||||
awaitingApproval,
|
||||
hasAtLeastOneLoginButton,
|
||||
showSecondFactor,
|
||||
canLoginLocal
|
||||
) {
|
||||
const classes = ["login-modal"];
|
||||
if (awaitingApproval) {
|
||||
classes.push("awaiting-approval");
|
||||
}
|
||||
if (hasAtLeastOneLoginButton) {
|
||||
if (hasAtLeastOneLoginButton && !showSecondFactor) {
|
||||
classes.push("has-alt-auth");
|
||||
}
|
||||
if (!canLoginLocal) {
|
||||
classes.push("no-local-login");
|
||||
}
|
||||
return classes.join(" ");
|
||||
},
|
||||
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
import { registerUnbound } from "discourse-common/lib/helpers";
|
||||
|
||||
registerUnbound("value-entered", function (value) {
|
||||
if (!value) {
|
||||
return "";
|
||||
} else if (value.length > 0) {
|
||||
return "value-entered";
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
});
|
|
@ -1,6 +1,10 @@
|
|||
{{#login-modal loginName=loginName loginPassword=loginPassword secondFactorToken=secondFactorToken action=(action "login")}}
|
||||
{{plugin-outlet name="login-before-modal-body" tagName=""}}
|
||||
{{#d-modal-body title="login.title" class=modalBodyClasses}}
|
||||
{{#d-modal-body class=modalBodyClasses}}
|
||||
<div class="login-welcome-header">
|
||||
<h1 class="login-title">{{i18n "login.header_title"}}</h1> <img src={{wavingHandURL}} alt="" class="waving-hand">
|
||||
<p class="login-subheader">{{i18n "login.subheader_title"}}</p>
|
||||
</div>
|
||||
{{#if showLoginButtons}}
|
||||
{{login-buttons
|
||||
showLoginWithEmailLink=showLoginWithEmailLink
|
||||
|
@ -12,32 +16,15 @@
|
|||
{{#if canLoginLocal}}
|
||||
<form id="login-form" method="post">
|
||||
<div id="credentials" class={{credentialsClass}}>
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="login-account-name">{{i18n "login.username"}}</label>
|
||||
</td>
|
||||
<td>
|
||||
{{text-field value=loginName type="email" placeholderKey="login.email_placeholder" id="login-account-name" autocorrect="off" autocapitalize="off" disabled=showSecondFactor}}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="login-account-password">{{i18n "login.password"}}</label>
|
||||
</td>
|
||||
<td>
|
||||
{{text-field value=loginPassword type="password" id="login-account-password" maxlength="200" disabled=showSecondFactor}}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>
|
||||
<a href id="forgot-password-link" {{action "showForgotPassword"}}>{{i18n "forgot_password.action"}}</a>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="input-group">
|
||||
{{input value=loginName class=(value-entered loginName)type="email" id="login-account-name" autocorrect="off" autocapitalize="off" disabled=showSecondFactor}}
|
||||
<label class="alt-placeholder" for="login-account-name">{{i18n "login.email_placeholder"}}</label>
|
||||
</div>
|
||||
<div class="input-group">
|
||||
{{input value=loginPassword class=(value-entered loginPassword) type="password" id="login-account-password" maxlength="200" disabled=showSecondFactor}}
|
||||
<label class="alt-placeholder" for="login-account-password">{{i18n "login.password"}}</label>
|
||||
<a href id="forgot-password-link" {{action "showForgotPassword"}}>{{i18n "forgot_password.action"}}</a>
|
||||
</div>
|
||||
</div>
|
||||
{{#second-factor-form
|
||||
secondFactorMethod=secondFactorMethod
|
||||
|
|
|
@ -1,172 +1,152 @@
|
|||
{{#create-account email=accountEmail disabled=submitDisabled action=(action "createAccount")}}
|
||||
{{#unless complete}}
|
||||
{{plugin-outlet name="create-account-before-modal-body"}}
|
||||
{{#d-modal-body title="create_account.title" class=modalBodyClasses}}
|
||||
|
||||
{{#unless hasAuthOptions}}
|
||||
{{login-buttons externalLogin=(action "externalLogin")}}
|
||||
{{/unless}}
|
||||
{{#d-modal-body class=modalBodyClasses}}
|
||||
|
||||
{{#if skipConfirmation}}
|
||||
{{loading-spinner size="large"}}
|
||||
{{/if}}
|
||||
|
||||
{{#if showCreateForm}}
|
||||
<div class="login-form">
|
||||
<form>
|
||||
<table>
|
||||
<tbody>
|
||||
<tr class="input create-account-email">
|
||||
<td class="label">
|
||||
<label for="new-account-email">
|
||||
{{i18n "user.email.title"}}
|
||||
{{~#if userFields~}}
|
||||
<span class="required">*</span>
|
||||
{{/if}}
|
||||
</label>
|
||||
</td>
|
||||
<td>
|
||||
{{#if emailValidated}}
|
||||
<span class="value">{{accountEmail}}</span>
|
||||
{{else}}
|
||||
{{input type="email" value=accountEmail id="new-account-email" name="email" autofocus="autofocus"}}
|
||||
<div class="create-account-form">
|
||||
<div class="login-welcome-header">
|
||||
<h1 class="login-title">{{i18n "create_account.header_title"}}</h1> <img src={{wavingHandURL}} alt="" class="waving-hand">
|
||||
<p class="login-subheader">{{i18n "create_account.subheader_title"}}</p>
|
||||
</div>
|
||||
{{#unless hasAuthOptions}}
|
||||
<div class="create-account-login-buttons">
|
||||
{{login-buttons externalLogin=(action "externalLogin")}}
|
||||
</div>
|
||||
{{/unless}}
|
||||
<div class="login-form">
|
||||
|
||||
<form>
|
||||
<div class="input-group">
|
||||
{{#if emailValidated}}
|
||||
<span class="value">{{accountEmail}}</span>
|
||||
{{else}}
|
||||
{{input type="email" value=accountEmail id="new-account-email" name="email" class=(value-entered accountEmail)}}
|
||||
<label class="alt-placeholder" for="new-account-email">
|
||||
{{i18n "user.email.title"}}
|
||||
{{~#if userFields~}}
|
||||
<span class="required">*</span>
|
||||
{{/if}}
|
||||
</td>
|
||||
</tr>
|
||||
</label>
|
||||
{{/if}}
|
||||
{{input-tip validation=emailValidation id="account-email-validation"}}
|
||||
<label class="more-info" for="new-account-email">{{i18n "user.email.instructions"}}</label>
|
||||
</div>
|
||||
|
||||
<tr class="instructions create-account-email">
|
||||
<td></td>
|
||||
{{input-tip validation=emailValidation id="account-email-validation"}}
|
||||
<td><label>{{i18n "user.email.instructions"}}</label></td>
|
||||
</tr>
|
||||
|
||||
<tr class="input">
|
||||
<td class="label">
|
||||
<label for="new-account-username">
|
||||
{{i18n "user.username.title"}}
|
||||
{{~#if userFields~}}
|
||||
<span class="required">*</span>
|
||||
{{/if}}
|
||||
</label>
|
||||
</td>
|
||||
<td>
|
||||
{{#if usernameDisabled}}
|
||||
<span class="value">{{accountUsername}}</span>
|
||||
{{else}}
|
||||
{{input value=accountUsername id="new-account-username" name="username" maxlength=maxUsernameLength autocomplete="discourse"}}
|
||||
<div class="input-group">
|
||||
{{#if usernameDisabled}}
|
||||
<span class="value">{{accountUsername}}</span>
|
||||
{{else}}
|
||||
{{input value=accountUsername class=(value-entered accountUsername) id="new-account-username" name="username" maxlength=maxUsernameLength
|
||||
autocomplete="discourse"}}
|
||||
<label class="alt-placeholder" for="new-account-username">
|
||||
{{i18n "user.username.title"}}
|
||||
{{~#if userFields~}}
|
||||
<span class="required">*</span>
|
||||
{{/if}}
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="instructions">
|
||||
<td></td>
|
||||
{{input-tip validation=usernameValidation id="username-validation"}}
|
||||
<td><label>{{i18n "user.username.instructions"}}</label></td>
|
||||
</tr>
|
||||
|
||||
{{#if fullnameRequired}}
|
||||
<tr class="input">
|
||||
<td class="label">
|
||||
<label for="new-account-name">
|
||||
{{i18n "user.name.title"}}
|
||||
{{#if siteSettings.full_name_required}}
|
||||
{{~#if userFields~}}
|
||||
<span class="required">*</span>
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
</label>
|
||||
</td>
|
||||
<td>
|
||||
{{#if nameDisabled}}
|
||||
<span class="value">{{accountName}}</span>
|
||||
{{else}}
|
||||
{{text-field value=accountName id="new-account-name"}}
|
||||
{{/if}}
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="instructions">
|
||||
<td></td>
|
||||
{{input-tip validation=nameValidation}}
|
||||
<td><label>{{nameInstructions}}</label></td>
|
||||
</tr>
|
||||
</label>
|
||||
{{/if}}
|
||||
|
||||
{{plugin-outlet
|
||||
name="create-account-before-password"
|
||||
noTags=true
|
||||
args=(hash
|
||||
accountName=accountName
|
||||
accountUsername=accountUsername
|
||||
accountPassword=accountPassword
|
||||
userFields=userFields
|
||||
authOptions=authOptions
|
||||
)
|
||||
}}
|
||||
{{input-tip validation=usernameValidation id="username-validation"}}
|
||||
<label class="more-info" for="new-account-username">{{i18n "user.username.instructions"}}</label>
|
||||
</div>
|
||||
|
||||
{{#if passwordRequired}}
|
||||
<tr class="input">
|
||||
<td class="label">
|
||||
<label for="new-account-password">
|
||||
{{i18n "user.password.title"}}
|
||||
<div class="input-group">
|
||||
{{#if fullnameRequired}}
|
||||
|
||||
{{#if nameDisabled}}
|
||||
<span class="value">{{accountName}}</span>
|
||||
{{else}}
|
||||
{{text-field value=accountName id="new-account-name" class=(value-entered accountName)}}
|
||||
<label class="alt-placeholder" for="new-account-name">
|
||||
{{i18n "user.name.title"}}
|
||||
{{#if siteSettings.full_name_required}}
|
||||
{{~#if userFields~}}
|
||||
<span class="required">*</span>
|
||||
{{/if}}
|
||||
</label>
|
||||
</td>
|
||||
<td>
|
||||
{{password-field value=accountPassword type="password" id="new-account-password" capsLockOn=capsLockOn}}
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="instructions">
|
||||
<td></td>
|
||||
{{input-tip validation=passwordValidation}}
|
||||
<td>
|
||||
<label>{{passwordInstructions}}</label>
|
||||
<div class="caps-lock-warning {{unless capsLockOn "hidden"}}">
|
||||
{{d-icon "exclamation-triangle"}} {{i18n "login.caps_lock_warning"}}
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{{/if}}
|
||||
</label>
|
||||
{{/if}}
|
||||
|
||||
{{input-tip validation=nameValidation}}
|
||||
<label class="more-info" for="new-account-name">{{nameInstructions}}</label>
|
||||
{{/if}}
|
||||
|
||||
<tr class="password-confirmation">
|
||||
<td><label for="new-account-password-confirmation">{{i18n "user.password_confirmation.title"}}</label></td>
|
||||
<td>
|
||||
{{honeypot-input id="new-account-confirmation" autocomplete="new-password" value=accountHoneypot}}
|
||||
{{input value=accountChallenge id="new-account-challenge"}}
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
{{#if requireInviteCode }}
|
||||
<tr class="invite-code">
|
||||
<td><label for="invite-code">{{i18n "user.invite_code.title"}}</label></td>
|
||||
<td>
|
||||
{{input value=inviteCode id="inviteCode"}}
|
||||
</td>
|
||||
<td><label>{{i18n "user.invite_code.instructions"}}</label></td>
|
||||
</tr>
|
||||
{{/if}}
|
||||
|
||||
{{plugin-outlet
|
||||
name="create-account-after-password"
|
||||
noTags=true
|
||||
args=(hash
|
||||
accountName=accountName
|
||||
accountUsername=accountUsername
|
||||
accountPassword=accountPassword
|
||||
userFields=userFields
|
||||
)
|
||||
}}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
{{#if userFields}}
|
||||
<div class="user-fields">
|
||||
{{#each userFields as |f|}}
|
||||
{{user-field field=f.field value=f.value}}
|
||||
{{/each}}
|
||||
</div>
|
||||
{{/if}}
|
||||
</form>
|
||||
|
||||
{{plugin-outlet
|
||||
name="create-account-before-password"
|
||||
noTags=true
|
||||
args=(hash
|
||||
accountName=accountName
|
||||
accountUsername=accountUsername
|
||||
accountPassword=accountPassword
|
||||
userFields=userFields
|
||||
authOptions=authOptions
|
||||
)
|
||||
}}
|
||||
|
||||
<div class="input-group">
|
||||
{{#if passwordRequired}}
|
||||
{{password-field value=accountPassword class=(value-entered accountPassword) type="password" id="new-account-password" autocomplete="current-password" capsLockOn=capsLockOn}}
|
||||
<label class="alt-placeholder" for="new-account-password">
|
||||
{{i18n "user.password.title"}}
|
||||
{{~#if userFields~}}
|
||||
<span class="required">*</span>
|
||||
{{/if}}
|
||||
</label>
|
||||
|
||||
{{input-tip validation=passwordValidation}}
|
||||
<label class="more-info" for="new-account-password">{{passwordInstructions}}</label>
|
||||
<div class="caps-lock-warning {{unless capsLockOn " hidden"}}">
|
||||
{{d-icon "exclamation-triangle"}} {{i18n "login.caps_lock_warning"}}
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
<div class="password-confirmation">
|
||||
<label for="new-account-password-confirmation">{{i18n "user.password_confirmation.title"}}</label>
|
||||
{{honeypot-input id="new-account-confirmation" autocomplete="new-password" value=accountHoneypot}}
|
||||
{{input value=accountChallenge id="new-account-challenge"}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{#if requireInviteCode }}
|
||||
<div class="input-group">
|
||||
{{input value=inviteCode class=(value-entered inviteCode) id="inviteCode"}}
|
||||
<label class="alt-placeholder" for="invite-code">{{i18n "user.invite_code.title"}}</label>
|
||||
<label class="more-info" for="invite-code">{{i18n "user.invite_code.instructions"}}</label>
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
{{plugin-outlet
|
||||
name="create-account-after-password"
|
||||
noTags=true
|
||||
args=(hash
|
||||
accountName=accountName
|
||||
accountUsername=accountUsername
|
||||
accountPassword=accountPassword
|
||||
userFields=userFields
|
||||
)
|
||||
}}
|
||||
|
||||
{{#if userFields}}
|
||||
<div class="user-fields">
|
||||
{{#each userFields as |f|}}
|
||||
<div class="input-group">
|
||||
{{!-- adding the value-entered class here to
|
||||
be able to detect if the user field has a value
|
||||
entered --}}
|
||||
{{user-field field=f.field value=f.value
|
||||
class=(value-entered f.value)}}
|
||||
</div>
|
||||
{{/each}}
|
||||
</div>
|
||||
{{/if}}
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{{/if}}
|
||||
{{/d-modal-body}}
|
||||
|
@ -185,10 +165,12 @@
|
|||
{{d-button class="btn-large" id="login-link" action=(route-action "showLogin") disabled=formSubmitted label="log_in"}}
|
||||
{{/unless}}
|
||||
|
||||
<div class="disclaimer">{{html-safe disclaimerHtml}}</div>
|
||||
<div class="disclaimer">
|
||||
{{html-safe disclaimerHtml}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{plugin-outlet name="create-account-after-modal-footer" tagName=""}}
|
||||
{{/if}}
|
||||
{{/unless}}
|
||||
{{/create-account}}
|
||||
{{/create-account}}
|
|
@ -1,85 +1,89 @@
|
|||
{{#login-modal loginName=loginName loginPassword=loginPassword secondFactorToken=secondFactorToken action=(action "login")}}
|
||||
{{plugin-outlet name="login-before-modal-body" tagName=""}}
|
||||
{{#d-modal-body title="login.title" class=modalBodyClasses}}
|
||||
{{#d-modal-body class=modalBodyClasses}}
|
||||
|
||||
{{#if canLoginLocal}}
|
||||
<form id="login-form" method="post">
|
||||
<div id="credentials" class={{credentialsClass}}>
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><label for="login-account-name">{{i18n "login.username"}}</label></td>
|
||||
<td>{{text-field value=loginName placeholderKey="login.email_placeholder" id="login-account-name" autocorrect="off" autocapitalize="off" autofocus="autofocus" disabled=disableLoginFields}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><label for="login-account-password">{{i18n "login.password"}}</label></td>
|
||||
<td>{{password-field value=loginPassword type="password" id="login-account-password" maxlength="200" capsLockOn=capsLockOn disabled=disableLoginFields}}</td>
|
||||
<td><a href id="forgot-password-link" {{action "forgotPassword"}}>{{i18n "forgot_password.action"}}</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td><div class="caps-lock-warning {{unless capsLockOn "hidden"}}">{{d-icon "exclamation-triangle"}} {{i18n "login.caps_lock_warning"}}</div></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="login-left-side">
|
||||
<div class="login-welcome-header">
|
||||
<h1 class="login-title">{{i18n "login.header_title"}}</h1> <img src={{wavingHandURL}} alt="" class="waving-hand">
|
||||
<p class="login-subheader">{{i18n "login.subheader_title"}}</p>
|
||||
</div>
|
||||
{{#second-factor-form
|
||||
secondFactorMethod=secondFactorMethod
|
||||
secondFactorToken=secondFactorToken
|
||||
class=secondFactorClass
|
||||
backupEnabled=backupEnabled
|
||||
isLogin=true}}
|
||||
{{#if showSecurityKey}}
|
||||
{{#security-key-form
|
||||
allowedCredentialIds=securityKeyAllowedCredentialIds
|
||||
challenge=securityKeyChallenge
|
||||
showSecurityKey=showSecurityKey
|
||||
showSecondFactor=showSecondFactor
|
||||
secondFactorMethod=secondFactorMethod
|
||||
otherMethodAllowed=otherMethodAllowed
|
||||
action=(action "authenticateSecurityKey")}}
|
||||
{{/security-key-form}}
|
||||
{{else}}
|
||||
{{second-factor-input value=secondFactorToken inputId="login-second-factor" secondFactorMethod=secondFactorMethod backupEnabled=backupEnabled}}
|
||||
<form id="login-form" method="post">
|
||||
<div id="credentials" class={{credentialsClass}}>
|
||||
<div class="input-group">
|
||||
{{input value=loginName type="email" id="login-account-name" class=(value-entered loginName) autocomplete="username" autocorrect="off" autocapitalize="off" disabled=showSecondFactor}}
|
||||
<label class="alt-placeholder" for="login-account-name">{{i18n "login.email_placeholder"}}</label>
|
||||
</div>
|
||||
<div class="input-group">
|
||||
{{input value=loginPassword type="password" class=(value-entered loginPassword) id="login-account-password" autocomplete="current-password" maxlength="200" capsLockOn=capsLockOn disabled=disableLoginFields}}
|
||||
<label class="alt-placeholder" for="login-account-password">{{i18n "login.password"}}</label>
|
||||
<a href id="forgot-password-link" {{action "forgotPassword"}}>{{i18n "forgot_password.action"}}</a>
|
||||
<div class="caps-lock-warning {{unless capsLockOn "hidden"}}">{{d-icon "exclamation-triangle"}} {{i18n "login.caps_lock_warning"}}</div>
|
||||
</div>
|
||||
</div>
|
||||
{{#second-factor-form
|
||||
secondFactorMethod=secondFactorMethod
|
||||
secondFactorToken=secondFactorToken
|
||||
class=secondFactorClass
|
||||
backupEnabled=backupEnabled
|
||||
isLogin=true}}
|
||||
{{#if showSecurityKey}}
|
||||
{{#security-key-form
|
||||
allowedCredentialIds=securityKeyAllowedCredentialIds
|
||||
challenge=securityKeyChallenge
|
||||
showSecurityKey=showSecurityKey
|
||||
showSecondFactor=showSecondFactor
|
||||
secondFactorMethod=secondFactorMethod
|
||||
otherMethodAllowed=otherMethodAllowed
|
||||
action=(action "authenticateSecurityKey")}}
|
||||
{{/security-key-form}}
|
||||
{{else}}
|
||||
{{second-factor-input value=secondFactorToken inputId="login-second-factor" secondFactorMethod=secondFactorMethod backupEnabled=backupEnabled}}
|
||||
{{/if}}
|
||||
{{/second-factor-form}}
|
||||
</form>
|
||||
<div class="modal-footer">
|
||||
{{#if canLoginLocal}}
|
||||
{{#unless showSecurityKey }}
|
||||
{{d-button
|
||||
action=(action "login")
|
||||
id="login-button"
|
||||
form="login-form"
|
||||
icon="unlock"
|
||||
label=loginButtonLabel
|
||||
disabled=loginDisabled
|
||||
class="btn btn-large btn-primary"}}
|
||||
{{/unless}}
|
||||
|
||||
{{#if showSignupLink}}
|
||||
{{d-button
|
||||
class="btn-large"
|
||||
id="new-account-link"
|
||||
action=(action "createAccount")
|
||||
label="create_account.title"}}
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
{{/second-factor-form}}
|
||||
</form>
|
||||
{{conditional-loading-spinner condition=showSpinner size="small"}}
|
||||
</div>
|
||||
</div>
|
||||
{{/if}}
|
||||
{{#if showLoginButtons}}
|
||||
{{login-buttons
|
||||
showLoginWithEmailLink=showLoginWithEmailLink
|
||||
processingEmailLink=processingEmailLink
|
||||
emailLogin=(action "emailLogin")
|
||||
externalLogin=(action "externalLogin")}}
|
||||
<div class="login-right-side">
|
||||
{{#if noLoginLocal}}
|
||||
<div class="login-welcome-header">
|
||||
<h1 class="login-title">{{i18n "login.header_title"}}</h1> <img src={{wavingHandURL}} alt="" class="waving-hand">
|
||||
<p class="login-subheader">{{i18n "login.subheader_title"}}</p>
|
||||
</div>
|
||||
{{/if}}
|
||||
{{login-buttons
|
||||
showLoginWithEmailLink=showLoginWithEmailLink
|
||||
processingEmailLink=processingEmailLink
|
||||
emailLogin=(action "emailLogin")
|
||||
externalLogin=(action "externalLogin")}}
|
||||
</div>
|
||||
{{/if}}
|
||||
{{/d-modal-body}}
|
||||
|
||||
<div class="modal-footer">
|
||||
{{#if canLoginLocal}}
|
||||
{{#unless showSecurityKey }}
|
||||
{{d-button
|
||||
action=(action "login")
|
||||
id="login-button"
|
||||
form="login-form"
|
||||
icon="unlock"
|
||||
label=loginButtonLabel
|
||||
disabled=loginDisabled
|
||||
class="btn btn-large btn-primary"}}
|
||||
{{/unless}}
|
||||
|
||||
{{#if showSignupLink}}
|
||||
{{d-button
|
||||
class="btn-large"
|
||||
id="new-account-link"
|
||||
action=(action "createAccount")
|
||||
label="create_account.title"}}
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
|
||||
{{conditional-loading-spinner condition=showSpinner size="small"}}
|
||||
</div>
|
||||
|
||||
{{plugin-outlet name="login-after-modal-footer" tagName=""}}
|
||||
|
||||
<div class={{alertClass}} id="login-alert">{{alert}}</div>
|
||||
|
|
|
@ -12,19 +12,185 @@
|
|||
display: none;
|
||||
}
|
||||
|
||||
#login-form {
|
||||
table {
|
||||
width: 100%;
|
||||
.login-modal:not(.hidden).has-alt-auth.no-local-login {
|
||||
min-width: fit-content;
|
||||
background: var(--secondary);
|
||||
#login-buttons:not(.hidden) {
|
||||
.btn.btn-social,
|
||||
.btn,
|
||||
.login-with-email-button {
|
||||
border: 1px solid var(--primary-low-mid);
|
||||
&:hover {
|
||||
background: var(--primary-very-low);
|
||||
}
|
||||
}
|
||||
}
|
||||
a {
|
||||
color: var(--primary-high);
|
||||
}
|
||||
|
||||
// Create Account + Login
|
||||
.d-modal.create-account,
|
||||
.d-modal.login-modal {
|
||||
.modal-inner-container {
|
||||
position: relative;
|
||||
}
|
||||
td {
|
||||
padding-right: 5px;
|
||||
.modal-body {
|
||||
padding: 0;
|
||||
}
|
||||
#credentials {
|
||||
tr:first-of-type {
|
||||
margin-bottom: 0.75em;
|
||||
.modal-header {
|
||||
border-bottom: none;
|
||||
padding: 0;
|
||||
position: absolute;
|
||||
top: 1em;
|
||||
right: 1em;
|
||||
z-index: z("max");
|
||||
}
|
||||
.login-welcome-header {
|
||||
z-index: z("modal", "content");
|
||||
display: grid;
|
||||
grid-template-columns: auto 1fr;
|
||||
grid-template-rows: auto 1fr;
|
||||
background: var(--secondary);
|
||||
.login-title {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.login-subheader {
|
||||
align-self: start;
|
||||
margin: 0;
|
||||
}
|
||||
.waving-hand {
|
||||
width: 35px;
|
||||
height: 35px;
|
||||
margin-left: 1em;
|
||||
align-self: center;
|
||||
}
|
||||
}
|
||||
#login-buttons {
|
||||
.btn {
|
||||
justify-content: flex-start;
|
||||
min-width: fit-content;
|
||||
}
|
||||
}
|
||||
.modal-footer {
|
||||
.inline-spinner {
|
||||
display: inline-flex;
|
||||
}
|
||||
}
|
||||
.modal-body.no-local-login + .modal-footer {
|
||||
display: none;
|
||||
}
|
||||
&.awaiting-approval {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
// Login Form Styles
|
||||
.login-modal:not(.hidden),
|
||||
.create-account {
|
||||
#login-form,
|
||||
.login-form {
|
||||
.input-group {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin-bottom: 1em;
|
||||
&:last-child {
|
||||
margin-bottom: 2em;
|
||||
}
|
||||
input {
|
||||
padding: 0.75em 0.5em;
|
||||
border-radius: 0.25em;
|
||||
min-width: 250px;
|
||||
box-shadow: none;
|
||||
margin-bottom: 0.25em;
|
||||
}
|
||||
input:focus {
|
||||
outline: none;
|
||||
border: 1px solid var(--tertiary);
|
||||
box-shadow: 0 0 0 2px rgba(var(--tertiary-rgb), 0.25);
|
||||
}
|
||||
label.more-info {
|
||||
color: var(--primary-medium);
|
||||
}
|
||||
label.alt-placeholder {
|
||||
color: var(--primary-medium);
|
||||
font-size: 16px;
|
||||
font-weight: normal;
|
||||
position: absolute;
|
||||
pointer-events: none;
|
||||
left: 1em;
|
||||
top: 10px;
|
||||
box-shadow: 0 0 0 0px rgba(var(--tertiary-rgb), 0);
|
||||
transition: 0.2s ease all;
|
||||
}
|
||||
input:focus + label.alt-placeholder,
|
||||
input.value-entered + label.alt-placeholder {
|
||||
top: -8px;
|
||||
left: calc(1em - 0.25em);
|
||||
background-color: var(--secondary);
|
||||
padding: 0 0.25em 0 0.25em;
|
||||
font-size: $font-down-1;
|
||||
color: var(--primary-medium);
|
||||
}
|
||||
input.alt-placeholder:invalid {
|
||||
color: var(--primary);
|
||||
}
|
||||
.tip:not(:empty) + label.more-info {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
#second-factor {
|
||||
input {
|
||||
width: 100%;
|
||||
padding: 0.75em 0.5em;
|
||||
border-radius: 0.25em;
|
||||
min-width: 250px;
|
||||
box-shadow: none;
|
||||
margin-bottom: 2em;
|
||||
}
|
||||
input:focus {
|
||||
outline: none;
|
||||
border: 1px solid var(--tertiary);
|
||||
box-shadow: 0 0 0 2px rgba(var(--tertiary-rgb), 0.25);
|
||||
}
|
||||
}
|
||||
|
||||
// user fields input groups will
|
||||
// be styled differently
|
||||
.user-fields .input-group {
|
||||
.user-field {
|
||||
&.text {
|
||||
label.control-label {
|
||||
color: var(--primary-medium);
|
||||
font-size: 16px;
|
||||
position: absolute;
|
||||
pointer-events: none;
|
||||
left: 1em;
|
||||
top: 12px;
|
||||
transition: 0.2s ease all;
|
||||
max-width: calc(100% - 2em);
|
||||
white-space: nowrap;
|
||||
display: inline-block;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
&.value-entered label.control-label,
|
||||
label.control-label.value-entered {
|
||||
top: -8px;
|
||||
left: calc(1em - 0.25em);
|
||||
background-color: var(--secondary);
|
||||
padding: 0 0.25em 0 0.25em;
|
||||
font-size: 14px;
|
||||
color: var(--primary-high);
|
||||
}
|
||||
}
|
||||
.controls .checkbox-label {
|
||||
input[type="checkbox"].ember-checkbox {
|
||||
width: 1em !important;
|
||||
min-width: unset;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -33,72 +199,21 @@
|
|||
cursor: pointer;
|
||||
}
|
||||
|
||||
.login-modal,
|
||||
.create-account {
|
||||
tbody {
|
||||
border: none;
|
||||
}
|
||||
tr {
|
||||
border: none;
|
||||
}
|
||||
tr:not(.instructions) {
|
||||
td {
|
||||
padding: 10px 0 0 0;
|
||||
}
|
||||
}
|
||||
td {
|
||||
label,
|
||||
input {
|
||||
margin-bottom: 0;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
.modal-footer {
|
||||
.inline-spinner {
|
||||
display: inline-flex;
|
||||
}
|
||||
}
|
||||
&.awaiting-approval {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.create-account {
|
||||
.disclaimer {
|
||||
color: var(--primary-medium);
|
||||
margin-top: 0.5em;
|
||||
}
|
||||
|
||||
tr.input span.value {
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.user-field {
|
||||
> label {
|
||||
margin-top: 0.75em;
|
||||
margin-bottom: 0;
|
||||
padding-top: 5px;
|
||||
}
|
||||
&:first-of-type > label {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
input[type="text"] {
|
||||
margin-bottom: 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.select-kit {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.controls {
|
||||
padding-top: 5px;
|
||||
label {
|
||||
width: auto;
|
||||
text-align: left;
|
||||
font-weight: normal;
|
||||
}
|
||||
.instructions {
|
||||
margin-top: 0.15em;
|
||||
color: var(--primary-medium);
|
||||
|
@ -162,15 +277,6 @@
|
|||
}
|
||||
}
|
||||
|
||||
.modal tr.instructions {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin-top: 0.15em;
|
||||
label {
|
||||
color: var(--primary-medium);
|
||||
}
|
||||
}
|
||||
|
||||
// alternate login / create new account buttons should be de-emphasized
|
||||
|
||||
button#login-link,
|
||||
|
|
|
@ -161,14 +161,16 @@
|
|||
// Social buttons
|
||||
// --------------------------------------------------
|
||||
|
||||
.btn-social {
|
||||
.d-icon {
|
||||
color: #fff;
|
||||
}
|
||||
color: #fff;
|
||||
background: #666;
|
||||
.btn-social,
|
||||
.login-with-email-button {
|
||||
border-radius: 0.25em;
|
||||
color: #000;
|
||||
background: #ffffff;
|
||||
border: 1px solid transparent;
|
||||
&:hover {
|
||||
color: #fff;
|
||||
color: #000 !important;
|
||||
background: #ececec !important;
|
||||
box-shadow: 0 0 0 2px rgba(var(--primary-rgb), 0.25);
|
||||
}
|
||||
&[href] {
|
||||
color: var(--secondary);
|
||||
|
@ -180,7 +182,6 @@
|
|||
&.google_oauth2 {
|
||||
background: var(--google);
|
||||
color: #333;
|
||||
border: 1px solid var(--primary-low);
|
||||
// non-FA SVG icon for Google in login-buttons.hbs
|
||||
.d-icon {
|
||||
opacity: 0.9;
|
||||
|
@ -188,38 +189,57 @@
|
|||
&:hover,
|
||||
&:focus {
|
||||
color: currentColor;
|
||||
background: var(--google-hover);
|
||||
}
|
||||
}
|
||||
|
||||
&.facebook {
|
||||
background: $facebook;
|
||||
&:hover,
|
||||
&:focus {
|
||||
background: var(--facebook-hover);
|
||||
.d-icon {
|
||||
color: $facebook;
|
||||
}
|
||||
&:hover {
|
||||
.d-icon {
|
||||
color: $facebook;
|
||||
}
|
||||
}
|
||||
}
|
||||
&.cas {
|
||||
background: var(--cas);
|
||||
.d-icon {
|
||||
color: var(--cas);
|
||||
}
|
||||
&:hover {
|
||||
.d-icon {
|
||||
color: var(--cas);
|
||||
}
|
||||
}
|
||||
}
|
||||
&.twitter {
|
||||
background: var(--twitter);
|
||||
&:hover,
|
||||
&:focus {
|
||||
background: var(--twitter-hover);
|
||||
.d-icon {
|
||||
color: var(--twitter);
|
||||
}
|
||||
&:hover {
|
||||
.d-icon {
|
||||
color: var(--twitter);
|
||||
}
|
||||
}
|
||||
}
|
||||
&.github {
|
||||
background: var(--github);
|
||||
&:hover,
|
||||
&:focus {
|
||||
background: var(--github-hover);
|
||||
.d-icon {
|
||||
color: var(--github);
|
||||
}
|
||||
&:hover {
|
||||
.d-icon {
|
||||
color: var(--github);
|
||||
}
|
||||
}
|
||||
}
|
||||
&.discord {
|
||||
background: var(--discord);
|
||||
&:hover,
|
||||
&:focus {
|
||||
background: var(--discord-hover);
|
||||
.d-icon {
|
||||
color: var(--discord);
|
||||
}
|
||||
&:hover {
|
||||
.d-icon {
|
||||
color: var(--discord);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ $google: #ffffff !default;
|
|||
$google-hover: darken($google, 5%) !default;
|
||||
$instagram: #e1306c !default;
|
||||
$instagram-hover: darken($instagram, 15%) !default;
|
||||
$facebook: #4267b2 !default;
|
||||
$facebook: #1877f2 !default;
|
||||
$facebook-hover: darken($facebook, 15%) !default;
|
||||
$cas: #70ba61 !default;
|
||||
$twitter: #1da1f2 !default;
|
||||
|
|
|
@ -3,21 +3,41 @@
|
|||
// create account modals
|
||||
.login-modal,
|
||||
.create-account {
|
||||
.modal-body {
|
||||
&.has-alt-auth {
|
||||
background: var(--tertiary);
|
||||
}
|
||||
@media (prefers-color-scheme: dark) {
|
||||
&.has-alt-auth {
|
||||
background: rgba(var(--tertiary-rgb), 0.5);
|
||||
}
|
||||
}
|
||||
}
|
||||
#modal-alert {
|
||||
padding: 15px 16px;
|
||||
}
|
||||
.btn-flat.btn.modal-close svg {
|
||||
color: rgba(var(--primary-rgb), 0.5);
|
||||
&:hover {
|
||||
color: rgba(var(--primary-rgb), 0.85);
|
||||
}
|
||||
}
|
||||
#login-buttons:not(.hidden) {
|
||||
display: flex;
|
||||
flex: 0 1 auto;
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
min-height: 75px;
|
||||
padding: 0 24px;
|
||||
order: 2;
|
||||
|
||||
button {
|
||||
display: flex;
|
||||
text-align: left;
|
||||
&:first-of-type {
|
||||
margin-top: 2.8em;
|
||||
}
|
||||
&:last-of-type {
|
||||
margin-bottom: 3em;
|
||||
}
|
||||
margin: 0.35em;
|
||||
white-space: nowrap;
|
||||
align-items: center;
|
||||
&:lang(zh_CN) {
|
||||
min-width: 200px;
|
||||
}
|
||||
|
@ -32,57 +52,14 @@
|
|||
}
|
||||
}
|
||||
|
||||
form {
|
||||
min-width: 300px;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
#modal-alert {
|
||||
max-width: 100%;
|
||||
margin-bottom: 0;
|
||||
padding: 8px 16px;
|
||||
padding: 8px 40px 8px 16px;
|
||||
min-height: 35px;
|
||||
}
|
||||
|
||||
.login-modal {
|
||||
#login-buttons:not(.hidden) {
|
||||
button {
|
||||
&:first-of-type {
|
||||
margin-top: 2.8em;
|
||||
}
|
||||
&:last-of-type {
|
||||
margin-bottom: 3em;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.create-account {
|
||||
#login-buttons:not(.hidden) {
|
||||
justify-content: flex-start;
|
||||
padding-top: 2.7em;
|
||||
+ .login-form {
|
||||
border-right: 1px solid var(--primary-low); // Only show border when login-form is present
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#login-form {
|
||||
box-sizing: border-box;
|
||||
flex: 1 0 auto;
|
||||
padding: 0 24px;
|
||||
+ #login-buttons {
|
||||
border-left: 1px solid var(--primary-low); // Only show border when login-form is present
|
||||
}
|
||||
}
|
||||
|
||||
tr:not(.instructions) {
|
||||
td {
|
||||
display: flex;
|
||||
padding: 5px 0 0 0;
|
||||
}
|
||||
}
|
||||
.tip,
|
||||
td label {
|
||||
.tip {
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
word-wrap: break-word;
|
||||
|
@ -95,25 +72,107 @@
|
|||
}
|
||||
|
||||
.has-alt-auth {
|
||||
.tip,
|
||||
td label {
|
||||
.tip {
|
||||
max-width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.login-modal:not(.hidden).has-alt-auth.no-local-login {
|
||||
padding: 0 2em !important;
|
||||
min-width: 350px !important;
|
||||
.login-right-side {
|
||||
width: 100%;
|
||||
padding: 2em 0;
|
||||
#login-buttons:not(.hidden) {
|
||||
width: 80%;
|
||||
.btn.btn-social:first-of-type {
|
||||
margin-top: 2em;
|
||||
}
|
||||
.btn.btn-social,
|
||||
.btn,
|
||||
.login-with-email-button {
|
||||
border: 1px solid var(--primary-low-mid);
|
||||
margin-bottom: 0.5em;
|
||||
&:hover {
|
||||
background: var(--primary-very-low) !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// styles used on
|
||||
// login modal only
|
||||
.d-modal.login-modal {
|
||||
.login-modal:not(.hidden) {
|
||||
padding: 0 !important;
|
||||
&.has-alt-auth {
|
||||
min-width: 700px;
|
||||
.login-left-side {
|
||||
width: calc(60% - 4em);
|
||||
padding: 1em 2em;
|
||||
}
|
||||
}
|
||||
.login-left-side {
|
||||
background: var(--secondary);
|
||||
width: calc(100% - 4em);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 1em 4em 1em 2em;
|
||||
.login-welcome-header {
|
||||
.login-title {
|
||||
font-size: 2.75em;
|
||||
}
|
||||
.login-subheader {
|
||||
font-size: 1.125em !important;
|
||||
}
|
||||
}
|
||||
#credentials {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start !important;
|
||||
}
|
||||
#login-form {
|
||||
margin: 1.5em 0 0 0;
|
||||
}
|
||||
.modal-footer {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
width: 100%;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
}
|
||||
}
|
||||
.login-right-side {
|
||||
display: none;
|
||||
}
|
||||
&.has-alt-auth .login-right-side {
|
||||
width: 40%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
#login-buttons {
|
||||
button {
|
||||
&.login-with-email-button {
|
||||
border-radius: 4px;
|
||||
.d-icon {
|
||||
color: #000 !important;
|
||||
}
|
||||
&:hover {
|
||||
box-shadow: 0 0 0 2px rgba(var(--primary-rgb), 0.25);
|
||||
.d-icon {
|
||||
color: #000 !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.modal-body,
|
||||
#credentials {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 15px 0;
|
||||
|
||||
tr {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
&.hidden {
|
||||
display: none;
|
||||
|
@ -125,111 +184,151 @@
|
|||
// create account
|
||||
// modal only
|
||||
.d-modal.create-account {
|
||||
.modal-body {
|
||||
display: flex;
|
||||
padding: 15px 0;
|
||||
.create-account {
|
||||
position: relative;
|
||||
.modal-body:not(.reorder-categories):not(.poll-ui-builder):not(.poll-breakdown) {
|
||||
max-height: 65vh !important;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
.create-account-form tr {
|
||||
.has-alt-auth .create-account-form {
|
||||
display: grid;
|
||||
grid-template-columns: 65% 35%;
|
||||
grid-template-rows: 20% 80%;
|
||||
grid-template-areas:
|
||||
"header login-buttons"
|
||||
"form login-buttons";
|
||||
}
|
||||
.create-account-form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
}
|
||||
.create-account-login-buttons {
|
||||
display: none;
|
||||
}
|
||||
.has-alt-auth .create-account-login-buttons {
|
||||
grid-area: login-buttons;
|
||||
padding: 1em;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
h3 {
|
||||
color: var(--secondary);
|
||||
text-align: center;
|
||||
}
|
||||
#login-buttons {
|
||||
button:first-of-type {
|
||||
margin-top: 0;
|
||||
}
|
||||
button {
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
}
|
||||
}
|
||||
.modal-body {
|
||||
display: flex;
|
||||
padding: 0;
|
||||
}
|
||||
.login-welcome-header {
|
||||
grid-area: header;
|
||||
padding: 1em 1em 1em 1em;
|
||||
.login-title {
|
||||
font-size: 2.75em;
|
||||
}
|
||||
.login-subheader {
|
||||
font-size: 1.125em !important;
|
||||
align-self: start;
|
||||
}
|
||||
}
|
||||
|
||||
.login-form {
|
||||
position: relative;
|
||||
display: flex;
|
||||
overflow: hidden;
|
||||
flex: 1 1 auto;
|
||||
.modal-body:not(.has-alt-auth) .login-form {
|
||||
&:after,
|
||||
&:before {
|
||||
width: 100%;
|
||||
}
|
||||
&:before {
|
||||
top: calc(8em - 10px) !important;
|
||||
}
|
||||
}
|
||||
|
||||
.has-alt-auth .login-form,
|
||||
.login-form {
|
||||
background: var(--secondary);
|
||||
padding: 1em;
|
||||
grid-area: form;
|
||||
overflow-y: scroll;
|
||||
&:after,
|
||||
&:before {
|
||||
content: "";
|
||||
display: block;
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
width: 65%;
|
||||
pointer-events: none;
|
||||
z-index: 100;
|
||||
margin-left: -1em;
|
||||
height: 1em;
|
||||
}
|
||||
&:after {
|
||||
bottom: 0;
|
||||
height: 35px;
|
||||
@media screen and (max-height: 650px) {
|
||||
height: 45px;
|
||||
}
|
||||
bottom: 93px;
|
||||
background-image: linear-gradient(
|
||||
to bottom,
|
||||
rgba(var(--secondary-rgb), 0),
|
||||
rgba(var(--secondary-rgb), 0.9)
|
||||
rgba(var(--secondary-rgb), 1)
|
||||
);
|
||||
}
|
||||
&:before {
|
||||
top: 0;
|
||||
height: 25px;
|
||||
top: calc(8em + 4px);
|
||||
background-image: linear-gradient(
|
||||
to top,
|
||||
rgba(var(--secondary-rgb), 0),
|
||||
rgba(var(--secondary-rgb), 1)
|
||||
);
|
||||
}
|
||||
form {
|
||||
box-sizing: border-box;
|
||||
padding: 16px 24px;
|
||||
margin-bottom: 0;
|
||||
max-height: 475px;
|
||||
@media screen and (max-height: 650px) {
|
||||
max-height: calc(65vh - 100px);
|
||||
> *:last-child {
|
||||
margin-bottom: 40px;
|
||||
}
|
||||
.input-group {
|
||||
margin-bottom: 1em;
|
||||
input {
|
||||
width: 100%;
|
||||
}
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
form,
|
||||
table {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
tr {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin-top: 0.15em;
|
||||
&.password-confirmation {
|
||||
display: none;
|
||||
input:not(.value-entered):not(:focus) + label.alt-placeholder {
|
||||
top: 12px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tr.input {
|
||||
input,
|
||||
label {
|
||||
margin-bottom: 0;
|
||||
width: 100%;
|
||||
.password-confirmation {
|
||||
display: none;
|
||||
}
|
||||
.tip {
|
||||
max-width: 340px;
|
||||
scrollbar-color: rgba(var(--primary-rgb), 0.5) transparent;
|
||||
&::-webkit-scrollbar {
|
||||
width: 15px;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-track {
|
||||
box-shadow: inset 0 0 14px 14px transparent;
|
||||
border: 4px solid transparent;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-thumb {
|
||||
box-shadow: inset 0 0 14px 14px rgba(var(--primary-rgb), 0.5);
|
||||
border: 4px solid transparent;
|
||||
border-radius: 14px;
|
||||
}
|
||||
|
||||
/* set button(top and bottom of the scrollbar) */
|
||||
&::-webkit-scrollbar-button {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.user-fields {
|
||||
margin-bottom: 20px;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
.user-field {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
&.confirm {
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
> label {
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.controls {
|
||||
margin-left: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.invites-show {
|
||||
|
@ -266,11 +365,7 @@
|
|||
|
||||
.login-form {
|
||||
.tip {
|
||||
&:not(:empty) + td {
|
||||
display: none;
|
||||
}
|
||||
&:not(:empty),
|
||||
&:empty + td {
|
||||
&:not(:empty) {
|
||||
min-height: 1.75em;
|
||||
&.bad .svg-icon {
|
||||
vertical-align: middle;
|
||||
|
|
|
@ -1,77 +1,110 @@
|
|||
// shared styles
|
||||
// used in both login and
|
||||
// create account modals
|
||||
.login-modal,
|
||||
.create-account {
|
||||
.d-modal.login-modal:not(.hidden),
|
||||
.d-modal.create-account {
|
||||
.modal-body {
|
||||
padding: 0;
|
||||
}
|
||||
&.fixed-modal .modal-inner-container {
|
||||
max-width: 350px;
|
||||
max-height: 90vh;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.close {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.login-welcome-header {
|
||||
padding: 1.5em 1em;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
#login-buttons:not(.hidden) {
|
||||
display: flex;
|
||||
flex: 1 0 auto;
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
width: 102%;
|
||||
padding-bottom: 10px;
|
||||
margin-left: -2%;
|
||||
padding: 1em;
|
||||
margin: 0;
|
||||
|
||||
button {
|
||||
.btn {
|
||||
padding: 0.53em 0.53em 0.53em 0.43em;
|
||||
border: 1px solid var(--primary-low);
|
||||
flex: 1 1 47%;
|
||||
max-width: 70%;
|
||||
margin: 1% 0 1% 2%;
|
||||
font-size: $font-0;
|
||||
margin: 0 0.5em 0.5em 0;
|
||||
white-space: nowrap;
|
||||
@media screen and (max-width: 360px) {
|
||||
font-size: $font-0;
|
||||
&:last-child {
|
||||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+ #login-form {
|
||||
border-top: 1px solid var(--primary-low);
|
||||
@media screen and (max-width: 750px) {
|
||||
#login-buttons:not(.hidden) {
|
||||
justify-content: center;
|
||||
.btn {
|
||||
&:nth-child(even) {
|
||||
margin: 0 0 0.5em 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
form {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
}
|
||||
#login-form,
|
||||
.login-form {
|
||||
padding: 1em;
|
||||
|
||||
table {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
tr {
|
||||
&.input td label {
|
||||
margin-top: 0.75em;
|
||||
}
|
||||
|
||||
td label {
|
||||
max-width: 280px;
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
&:not(.instructions) td {
|
||||
padding: 2px 0 0 0;
|
||||
}
|
||||
|
||||
&:not(.password-confirmation) {
|
||||
form {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.input-group {
|
||||
input {
|
||||
height: 2.25em;
|
||||
margin-bottom: 0.25em;
|
||||
}
|
||||
margin-bottom: 1em;
|
||||
label.alt-placeholder {
|
||||
top: 8px;
|
||||
}
|
||||
input:focus + label,
|
||||
input.value-entered + label.alt-placeholder {
|
||||
top: -10px;
|
||||
}
|
||||
input.alt-placeholder:invalid {
|
||||
color: var(--primary);
|
||||
}
|
||||
label.more-info {
|
||||
color: var(--primary-medium);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.tip {
|
||||
&:not(:empty) + td {
|
||||
display: none;
|
||||
.user-fields .input-group {
|
||||
.text.user-field {
|
||||
label.control-label {
|
||||
top: 8px;
|
||||
}
|
||||
&.value-entered label.control-label,
|
||||
label.control-label.value-entered {
|
||||
top: -10px;
|
||||
left: calc(1em - 0.25em);
|
||||
background-color: var(--secondary);
|
||||
padding: 0 0.25em 0 0.25em;
|
||||
font-size: 14px;
|
||||
color: var(--primary-medium);
|
||||
}
|
||||
}
|
||||
.controls .checkbox-label {
|
||||
align-items: center;
|
||||
input[type="checkbox"].ember-checkbox {
|
||||
height: 15px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -105,38 +138,21 @@
|
|||
.d-modal.login-modal {
|
||||
#credentials {
|
||||
width: 100%;
|
||||
tr {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
}
|
||||
|
||||
#login-form {
|
||||
margin-bottom: 0.75em;
|
||||
td {
|
||||
padding: 0;
|
||||
width: 100%;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
label {
|
||||
float: left;
|
||||
display: block;
|
||||
}
|
||||
textarea,
|
||||
input,
|
||||
select {
|
||||
font-size: $font-up-1;
|
||||
clear: left;
|
||||
margin-top: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tr {
|
||||
td label {
|
||||
margin-top: 0.75em;
|
||||
padding: 4px 0;
|
||||
}
|
||||
.login-modal:not(.hidden).has-alt-auth.no-local-login {
|
||||
#login-buttons:not(.hidden) {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -146,24 +162,31 @@
|
|||
|
||||
#discourse-modal .create-account .modal-body {
|
||||
max-height: 60vh !important;
|
||||
overflow: hidden;
|
||||
@media screen and (max-height: 575px) {
|
||||
max-height: 50vh !important;
|
||||
}
|
||||
}
|
||||
|
||||
.d-modal.create-account {
|
||||
.create-account-form {
|
||||
overflow-y: auto;
|
||||
.login-welcome-header {
|
||||
width: calc(100% - 2em);
|
||||
position: sticky;
|
||||
position: -webkit-sticky;
|
||||
top: 0;
|
||||
background-color: var(--secondary);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.create-account .modal-body {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
tr.instructions {
|
||||
label {
|
||||
color: var(--primary-med-or-secondary-med);
|
||||
}
|
||||
}
|
||||
|
||||
#login-buttons {
|
||||
border-bottom: 1px solid var(--primary-low);
|
||||
}
|
||||
|
||||
.login-form {
|
||||
margin-bottom: 0.75em;
|
||||
}
|
||||
|
@ -178,16 +201,6 @@
|
|||
.user-field {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
> label {
|
||||
width: auto;
|
||||
}
|
||||
.controls {
|
||||
margin-left: 0;
|
||||
label {
|
||||
line-height: $line-height-medium;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1674,8 +1674,10 @@ en:
|
|||
search_hint: "username, email or IP address"
|
||||
|
||||
create_account:
|
||||
header_title: "Welcome!"
|
||||
subheader_title: "Let's create your account"
|
||||
disclaimer: "By registering, you agree to the <a href='%{privacy_link}' target='blank'>privacy policy</a> and <a href='%{tos_link}' target='blank'>terms of service</a>."
|
||||
title: "Create New Account"
|
||||
title: "Create your account"
|
||||
failed: "Something went wrong, perhaps this email is already registered, try the forgot password link"
|
||||
|
||||
forgot_password:
|
||||
|
@ -1709,6 +1711,8 @@ en:
|
|||
confirm_button: Finish Login
|
||||
|
||||
login:
|
||||
header_title: "Welcome Back"
|
||||
subheader_title: "Log in to your account"
|
||||
title: "Log In"
|
||||
username: "User"
|
||||
password: "Password"
|
||||
|
@ -1724,7 +1728,7 @@ en:
|
|||
security_key_not_allowed_error: "The security key authentication process either timed out or was cancelled."
|
||||
security_key_no_matching_credential_error: "No matching credentials could be found in the provided security key."
|
||||
security_key_support_missing_error: "Your current device or browser does not support the use of security keys. Please use a different method."
|
||||
email_placeholder: "email or username"
|
||||
email_placeholder: "email / username"
|
||||
caps_lock_warning: "Caps Lock is on"
|
||||
error: "Unknown error"
|
||||
cookies_error: "Your browser seems to have cookies disabled. You might not be able to log in without enabling them first."
|
||||
|
|
Loading…
Reference in New Issue