From 4580595bd8c349162e4254296ce70e3caa597e4f Mon Sep 17 00:00:00 2001 From: Jordan Vidrine <30537603+jordanvidrine@users.noreply.github.com> Date: Wed, 10 Feb 2021 14:53:18 -0600 Subject: [PATCH] Login signup zazz (#11957) This PR re-styles the login and create account modals. --- .../admin/addon/templates/user-fields.hbs | 2 +- .../app/components/create-account.js | 47 +++ .../app/controllers/create-account.js | 10 + .../discourse/app/controllers/login.js | 33 +- .../discourse/app/helpers/value-entered.js | 11 + .../app/templates/mobile/modal/login.hbs | 41 +- .../app/templates/modal/create-account.hbs | 284 +++++++------- .../discourse/app/templates/modal/login.hbs | 146 ++++---- app/assets/stylesheets/common/base/login.scss | 246 ++++++++---- .../common/components/buttons.scss | 72 ++-- .../common/foundation/variables.scss | 2 +- app/assets/stylesheets/desktop/login.scss | 351 +++++++++++------- app/assets/stylesheets/mobile/login.scss | 173 +++++---- config/locales/client.en.yml | 8 +- 14 files changed, 865 insertions(+), 561 deletions(-) create mode 100644 app/assets/javascripts/discourse/app/helpers/value-entered.js diff --git a/app/assets/javascripts/admin/addon/templates/user-fields.hbs b/app/assets/javascripts/admin/addon/templates/user-fields.hbs index a14119e92bb..ed0c5ba7443 100644 --- a/app/assets/javascripts/admin/addon/templates/user-fields.hbs +++ b/app/assets/javascripts/admin/addon/templates/user-fields.hbs @@ -21,4 +21,4 @@ label="admin.user_fields.create" icon="plus"}} - + \ No newline at end of file diff --git a/app/assets/javascripts/discourse/app/components/create-account.js b/app/assets/javascripts/discourse/app/components/create-account.js index 265a1260328..c1aabdca522 100644 --- a/app/assets/javascripts/discourse/app/components/create-account.js +++ b/app/assets/javascripts/discourse/app/components/create-account.js @@ -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); + } + } }, }); diff --git a/app/assets/javascripts/discourse/app/controllers/create-account.js b/app/assets/javascripts/discourse/app/controllers/create-account.js index fce8b5e08a3..a5d087d0db5 100644 --- a/app/assets/javascripts/discourse/app/controllers/create-account.js +++ b/app/assets/javascripts/discourse/app/controllers/create-account.js @@ -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 = []; diff --git a/app/assets/javascripts/discourse/app/controllers/login.js b/app/assets/javascripts/discourse/app/controllers/login.js index d6150a22855..aabc8444707 100644 --- a/app/assets/javascripts/discourse/app/controllers/login.js +++ b/app/assets/javascripts/discourse/app/controllers/login.js @@ -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(" "); }, diff --git a/app/assets/javascripts/discourse/app/helpers/value-entered.js b/app/assets/javascripts/discourse/app/helpers/value-entered.js new file mode 100644 index 00000000000..4a6907ae23b --- /dev/null +++ b/app/assets/javascripts/discourse/app/helpers/value-entered.js @@ -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 ""; + } +}); diff --git a/app/assets/javascripts/discourse/app/templates/mobile/modal/login.hbs b/app/assets/javascripts/discourse/app/templates/mobile/modal/login.hbs index 37279abb92c..15472d6f885 100644 --- a/app/assets/javascripts/discourse/app/templates/mobile/modal/login.hbs +++ b/app/assets/javascripts/discourse/app/templates/mobile/modal/login.hbs @@ -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}} +
+

{{i18n "login.header_title"}}

+

{{i18n "login.subheader_title"}}

+
{{#if showLoginButtons}} {{login-buttons showLoginWithEmailLink=showLoginWithEmailLink @@ -12,32 +16,15 @@ {{#if canLoginLocal}}
- - - - - - - - - - - - - - - -
- - - {{text-field value=loginName type="email" placeholderKey="login.email_placeholder" id="login-account-name" autocorrect="off" autocapitalize="off" disabled=showSecondFactor}} -
- - - {{text-field value=loginPassword type="password" id="login-account-password" maxlength="200" disabled=showSecondFactor}} -
- {{i18n "forgot_password.action"}} -
+
+ {{input value=loginName class=(value-entered loginName)type="email" id="login-account-name" autocorrect="off" autocapitalize="off" disabled=showSecondFactor}} + +
+
+ {{input value=loginPassword class=(value-entered loginPassword) type="password" id="login-account-password" maxlength="200" disabled=showSecondFactor}} + + {{i18n "forgot_password.action"}} +
{{#second-factor-form secondFactorMethod=secondFactorMethod diff --git a/app/assets/javascripts/discourse/app/templates/modal/create-account.hbs b/app/assets/javascripts/discourse/app/templates/modal/create-account.hbs index 85ee9a1eb9e..0b7eb81f01d 100644 --- a/app/assets/javascripts/discourse/app/templates/modal/create-account.hbs +++ b/app/assets/javascripts/discourse/app/templates/modal/create-account.hbs @@ -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}} -
- - - - - - - + + {{/if}} + {{input-tip validation=emailValidation id="account-email-validation"}} + + - - - {{input-tip validation=emailValidation id="account-email-validation"}} - - - - - - - - - - {{input-tip validation=usernameValidation id="username-validation"}} - - - - {{#if fullnameRequired}} - - - - - - - {{input-tip validation=nameValidation}} - - + {{/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"}} + + - {{#if passwordRequired}} - - - - - - - {{input-tip validation=passwordValidation}} - - + {{/if}} + + {{/if}} + + {{input-tip validation=nameValidation}} + {{/if}} - - - - - - - {{#if requireInviteCode }} - - - - - - {{/if}} - - {{plugin-outlet - name="create-account-after-password" - noTags=true - args=(hash - accountName=accountName - accountUsername=accountUsername - accountPassword=accountPassword - userFields=userFields - ) - }} - -
- - - {{#if usernameDisabled}} - {{accountUsername}} - {{else}} - {{input value=accountUsername id="new-account-username" name="username" maxlength=maxUsernameLength autocomplete="discourse"}} +
+ {{#if usernameDisabled}} + {{accountUsername}} + {{else}} + {{input value=accountUsername class=(value-entered accountUsername) id="new-account-username" name="username" maxlength=maxUsernameLength + autocomplete="discourse"}} +
- - - {{#if nameDisabled}} - {{accountName}} - {{else}} - {{text-field value=accountName id="new-account-name"}} - {{/if}} -
- - {{password-field value=accountPassword type="password" id="new-account-password" capsLockOn=capsLockOn}} -
- -
- {{d-icon "exclamation-triangle"}} {{i18n "login.caps_lock_warning"}} -
-
- {{honeypot-input id="new-account-confirmation" autocomplete="new-password" value=accountHoneypot}} - {{input value=accountChallenge id="new-account-challenge"}} -
- {{input value=inviteCode id="inviteCode"}} -
- - {{#if userFields}} -
- {{#each userFields as |f|}} - {{user-field field=f.field value=f.value}} - {{/each}}
- {{/if}} - + + {{plugin-outlet + name="create-account-before-password" + noTags=true + args=(hash + accountName=accountName + accountUsername=accountUsername + accountPassword=accountPassword + userFields=userFields + authOptions=authOptions + ) + }} + +
+ {{#if passwordRequired}} + {{password-field value=accountPassword class=(value-entered accountPassword) type="password" id="new-account-password" autocomplete="current-password" capsLockOn=capsLockOn}} + + + {{input-tip validation=passwordValidation}} + +
+ {{d-icon "exclamation-triangle"}} {{i18n "login.caps_lock_warning"}} +
+ {{/if}} + +
+ + {{honeypot-input id="new-account-confirmation" autocomplete="new-password" value=accountHoneypot}} + {{input value=accountChallenge id="new-account-challenge"}} +
+
+ + {{#if requireInviteCode }} +
+ {{input value=inviteCode class=(value-entered inviteCode) id="inviteCode"}} + + +
+ {{/if}} + + {{plugin-outlet + name="create-account-after-password" + noTags=true + args=(hash + accountName=accountName + accountUsername=accountUsername + accountPassword=accountPassword + userFields=userFields + ) + }} + + {{#if userFields}} +
+ {{#each userFields as |f|}} +
+ {{!-- 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)}} +
+ {{/each}} +
+ {{/if}} + +
{{/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}} -
{{html-safe disclaimerHtml}}
+
+ {{html-safe disclaimerHtml}} +
{{plugin-outlet name="create-account-after-modal-footer" tagName=""}} {{/if}} {{/unless}} -{{/create-account}} +{{/create-account}} \ No newline at end of file diff --git a/app/assets/javascripts/discourse/app/templates/modal/login.hbs b/app/assets/javascripts/discourse/app/templates/modal/login.hbs index ca9faa98d92..1753a34821f 100644 --- a/app/assets/javascripts/discourse/app/templates/modal/login.hbs +++ b/app/assets/javascripts/discourse/app/templates/modal/login.hbs @@ -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}} -
-
- - - - - - - - - - - - - - - - - -
{{text-field value=loginName placeholderKey="login.email_placeholder" id="login-account-name" autocorrect="off" autocapitalize="off" autofocus="autofocus" disabled=disableLoginFields}}
{{password-field value=loginPassword type="password" id="login-account-password" maxlength="200" capsLockOn=capsLockOn disabled=disableLoginFields}}{{i18n "forgot_password.action"}}
{{d-icon "exclamation-triangle"}} {{i18n "login.caps_lock_warning"}}
+ {{/if}} {{#if showLoginButtons}} - {{login-buttons - showLoginWithEmailLink=showLoginWithEmailLink - processingEmailLink=processingEmailLink - emailLogin=(action "emailLogin") - externalLogin=(action "externalLogin")}} + {{/if}} {{/d-modal-body}} - - {{plugin-outlet name="login-after-modal-footer" tagName=""}}
{{alert}}
diff --git a/app/assets/stylesheets/common/base/login.scss b/app/assets/stylesheets/common/base/login.scss index 512d0089016..84fb9eb1de6 100644 --- a/app/assets/stylesheets/common/base/login.scss +++ b/app/assets/stylesheets/common/base/login.scss @@ -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, diff --git a/app/assets/stylesheets/common/components/buttons.scss b/app/assets/stylesheets/common/components/buttons.scss index 1fe5e8ba001..933bb7ce14a 100644 --- a/app/assets/stylesheets/common/components/buttons.scss +++ b/app/assets/stylesheets/common/components/buttons.scss @@ -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); + } } } } diff --git a/app/assets/stylesheets/common/foundation/variables.scss b/app/assets/stylesheets/common/foundation/variables.scss index 3cf9b31269a..2712f8272bb 100644 --- a/app/assets/stylesheets/common/foundation/variables.scss +++ b/app/assets/stylesheets/common/foundation/variables.scss @@ -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; diff --git a/app/assets/stylesheets/desktop/login.scss b/app/assets/stylesheets/desktop/login.scss index f89e06d1047..58836208824 100644 --- a/app/assets/stylesheets/desktop/login.scss +++ b/app/assets/stylesheets/desktop/login.scss @@ -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; diff --git a/app/assets/stylesheets/mobile/login.scss b/app/assets/stylesheets/mobile/login.scss index c6932cb39bd..2d5cc7f45ff 100644 --- a/app/assets/stylesheets/mobile/login.scss +++ b/app/assets/stylesheets/mobile/login.scss @@ -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; - } - } } } diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml index 08974637f23..eeb81210efc 100644 --- a/config/locales/client.en.yml +++ b/config/locales/client.en.yml @@ -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 privacy policy and terms of service." - 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."