From c601cca288d4356efdebd48587c251929c776047 Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Thu, 30 Nov 2023 15:58:12 +0100 Subject: [PATCH] :sparkles: Improve design of input fields --- .../styles/common/refactor/design-tokens.scss | 1 + frontend/src/app/main/ui/auth/recovery.cljs | 2 + frontend/src/app/main/ui/auth/register.cljs | 3 + .../src/app/main/ui/components/forms.cljs | 63 ++++++++++--------- .../src/app/main/ui/components/forms.scss | 60 +++++++++++++++++- .../app/main/ui/settings/access_tokens.cljs | 1 + .../app/main/ui/settings/change_email.cljs | 2 + .../src/app/main/ui/settings/feedback.cljs | 3 +- .../src/app/main/ui/settings/password.cljs | 2 + .../src/app/main/ui/settings/profile.cljs | 1 - 10 files changed, 106 insertions(+), 32 deletions(-) diff --git a/frontend/resources/styles/common/refactor/design-tokens.scss b/frontend/resources/styles/common/refactor/design-tokens.scss index ff35b9635..c68d1d650 100644 --- a/frontend/resources/styles/common/refactor/design-tokens.scss +++ b/frontend/resources/styles/common/refactor/design-tokens.scss @@ -151,6 +151,7 @@ --input-foreground-color-disabled: var(--color-foreground-secondary); --input-border-color-disabled: var(--color-background-quaternary); --input-border-color-error: var(--error-color); + --input-border-color-success: var(--color-accent-primary); --input-details-color: var(--color-background-primary); --input-checkbox-background-color-rest: var(--color-background-quaternary); --input-checkbox-border-color-active: var(--color-background-quaternary); diff --git a/frontend/src/app/main/ui/auth/recovery.cljs b/frontend/src/app/main/ui/auth/recovery.cljs index 7925de065..e8828c003 100644 --- a/frontend/src/app/main/ui/auth/recovery.cljs +++ b/frontend/src/app/main/ui/auth/recovery.cljs @@ -68,12 +68,14 @@ [:div {:class (stl/css :fields-row)} [:& fm/input {:type "password" :name :password-1 + :show-success? true :label (tr "auth.new-password") :class (stl/css :form-field)}]] [:div {:class (stl/css :fields-row)} [:& fm/input {:type "password" :name :password-2 + :show-success? true :label (tr "auth.confirm-password") :class (stl/css :form-field)}]] diff --git a/frontend/src/app/main/ui/auth/register.cljs b/frontend/src/app/main/ui/auth/register.cljs index 01b25fd32..da8f5277a 100644 --- a/frontend/src/app/main/ui/auth/register.cljs +++ b/frontend/src/app/main/ui/auth/register.cljs @@ -121,11 +121,13 @@ :name :email :label (tr "auth.email") :data-test "email-input" + :show-success? true :class (stl/css :form-field)}]] [:div {:class (stl/css :fields-row)} [:& fm/input {:name :password :hint (tr "auth.password-length-hint") :label (tr "auth.password") + :show-success? true :type "password" :class (stl/css :form-field)}]] @@ -310,6 +312,7 @@ [:& fm/input {:name :fullname :label (tr "auth.fullname") :type "text" + :show-success? true :class (stl/css :form-field)}]] (when (contains? cf/flags :terms-and-privacy-checkbox) diff --git a/frontend/src/app/main/ui/components/forms.cljs b/frontend/src/app/main/ui/components/forms.cljs index fc6db4641..11b633cc8 100644 --- a/frontend/src/app/main/ui/components/forms.cljs +++ b/frontend/src/app/main/ui/components/forms.cljs @@ -27,8 +27,9 @@ (def use-form fm/use-form) (mf/defc input - [{:keys [label help-icon disabled form hint trim children data-test on-change-value placeholder] :as props}] + [{:keys [label help-icon disabled form hint trim children data-test on-change-value placeholder show-success?] :as props}] (let [new-css-system (mf/use-ctx ctx/new-css-system) + input-type (get props :type "text") input-name (get props :name) more-classes (get props :class) @@ -65,25 +66,6 @@ on-change-value (or on-change-value (constantly nil)) - klass (str more-classes " " - (dom/classnames - :focus @focus? - :valid (and touched? (not error)) - :invalid (and touched? error) - :disabled disabled - :empty (and is-text? (str/empty? value)) - :with-icon (not (nil? help-icon')) - :custom-input is-text? - :input-radio is-radio? - :input-checkbox is-checkbox?)) - - new-classes (dm/str more-classes " " - (stl/css-case - :input-wrapper true - :global/invalid (and touched? error) - :checkbox is-checkbox? - :global/disabled disabled)) - swap-text-password (fn [] (swap! type' (fn [input-type] @@ -100,9 +82,7 @@ on-blur (fn [_] - (reset! focus? false) - (when-not (get-in @form [:touched input-name]) - (swap! form assoc-in [:touched input-name] true))) + (reset! focus? false)) on-click (fn [_] @@ -126,10 +106,19 @@ (cond-> (and value is-checkbox?) (assoc :default-checked value)) (cond-> (and touched? (:message error)) (assoc "aria-invalid" "true" "aria-describedby" (dm/str "error-" input-name))) - (obj/clj->props))] + (obj/clj->props)) + + show-valid? (and show-success? touched? (not error)) + show-invalid? (and touched? error)] (if new-css-system - [:div {:class new-classes} + [:div {:class (dm/str more-classes " " + (stl/css-case + :input-wrapper true + :valid show-valid? + :invalid show-invalid? + :checkbox is-checkbox? + :disabled disabled))} [:* (cond (some? label) @@ -152,7 +141,15 @@ [:span {:class (stl/css :help-icon) :on-click (when (= "password" input-type) swap-text-password)} - help-icon'])])] + help-icon']) + + (when show-valid? + [:span {:class (stl/css :valid-icon)} + i/tick-refactor]) + + (when show-invalid? + [:span {:class (stl/css :invalid-icon)} + i/close-refactor])])] (some? children) [:label {:for (name input-name)} @@ -171,9 +168,19 @@ (string? hint) [:div {:class (stl/css :hint)} hint])]] - + ;;OLD [:div - {:class klass} + {:class (str more-classes " " + (dom/classnames + :focus @focus? + :valid (and touched? (not error)) + :invalid (and touched? error) + :disabled disabled + :empty (and is-text? (str/empty? value)) + :with-icon (not (nil? help-icon')) + :custom-input is-text? + :input-radio is-radio? + :input-checkbox is-checkbox?))} [:* [:> :input props] (cond diff --git a/frontend/src/app/main/ui/components/forms.scss b/frontend/src/app/main/ui/components/forms.scss index d6e9af1fb..2bb900528 100644 --- a/frontend/src/app/main/ui/components/forms.scss +++ b/frontend/src/app/main/ui/components/forms.scss @@ -51,12 +51,31 @@ caret-color: var(--input-foreground-color-active); } } - &:global(.invalid) { + &.valid { + input { + border: $s-1 solid var(--input-border-color-success); + @extend .disabled-input; + &:hover, + &:focus { + border: $s-1 solid var(--input-border-color-success); + } + } + } + &.invalid { input { border: $s-1 solid var(--input-border-color-error); @extend .disabled-input; + &:hover, + &:focus { + border: $s-1 solid var(--input-border-color-error); + } } } + + &.valid .help-icon, + &.invalid .help-icon { + right: $s-40; + } } .input-and-icon { @@ -69,7 +88,7 @@ .help-icon { cursor: pointer; position: absolute; - right: $s-12; + right: $s-16; top: calc(50% - $s-8); svg { @extend .button-icon-small; @@ -78,6 +97,43 @@ height: $s-16; } } +.invalid-icon { + width: $s-16; + height: $s-16; + background: var(--input-border-color-error); + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + position: absolute; + right: $s-16; + top: calc(50% - $s-8); + svg { + width: $s-12; + height: $s-12; + stroke: var(--input-background-color); + } +} + +.valid-icon { + width: $s-16; + height: $s-16; + background: var(--input-border-color-success); + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + position: absolute; + right: $s-16; + top: calc(50% - $s-8); + svg { + width: $s-12; + height: $s-12; + fill: var(--input-border-color-success); + stroke: var(--input-background-color); + } +} + .error { color: var(--input-border-color-error); width: 100%; diff --git a/frontend/src/app/main/ui/settings/access_tokens.cljs b/frontend/src/app/main/ui/settings/access_tokens.cljs index de1ec0a7c..a044455ae 100644 --- a/frontend/src/app/main/ui/settings/access_tokens.cljs +++ b/frontend/src/app/main/ui/settings/access_tokens.cljs @@ -126,6 +126,7 @@ :name :name :disabled @created? :label (tr "modals.create-access-token.name.label") + :show-success? true :placeholder (tr "modals.create-access-token.name.placeholder")}]] [:div {:class (stl/css :fields-row)} diff --git a/frontend/src/app/main/ui/settings/change_email.cljs b/frontend/src/app/main/ui/settings/change_email.cljs index 391fa4475..6cd6ae69f 100644 --- a/frontend/src/app/main/ui/settings/change_email.cljs +++ b/frontend/src/app/main/ui/settings/change_email.cljs @@ -122,6 +122,7 @@ :name :email-1 :label (tr "modals.change-email.new-email") :trim true + :show-success? true :on-change-value on-email-change}]] [:div {:class (stl/css :fields-row)} @@ -129,6 +130,7 @@ :name :email-2 :label (tr "modals.change-email.confirm-email") :trim true + :show-success? true :on-change-value on-email-change}]]] [:div {:class (stl/css :modal-footer)} diff --git a/frontend/src/app/main/ui/settings/feedback.cljs b/frontend/src/app/main/ui/settings/feedback.cljs index d59185f13..d8e41518b 100644 --- a/frontend/src/app/main/ui/settings/feedback.cljs +++ b/frontend/src/app/main/ui/settings/feedback.cljs @@ -73,7 +73,8 @@ [:div {:class (stl/css :fields-row)} [:& fm/input {:label (tr "feedback.subject") - :name :subject}]] + :name :subject + :show-success? true}]] [:div {:class (stl/css :fields-row :description)} [:& fm/textarea {:label (tr "feedback.description") diff --git a/frontend/src/app/main/ui/settings/password.cljs b/frontend/src/app/main/ui/settings/password.cljs index 1d868b08c..0b9b1b5a0 100644 --- a/frontend/src/app/main/ui/settings/password.cljs +++ b/frontend/src/app/main/ui/settings/password.cljs @@ -95,12 +95,14 @@ [:& fm/input {:type "password" :name :password-1 + :show-success? true :label (t locale "labels.new-password")}]] [:div {:class (stl/css :fields-row)} [:& fm/input {:type "password" :name :password-2 + :show-success? true :label (t locale "labels.confirm-password")}]] [:> fm/submit-button* diff --git a/frontend/src/app/main/ui/settings/profile.cljs b/frontend/src/app/main/ui/settings/profile.cljs index a6bb4ad30..b946b6846 100644 --- a/frontend/src/app/main/ui/settings/profile.cljs +++ b/frontend/src/app/main/ui/settings/profile.cljs @@ -75,7 +75,6 @@ {:type "email" :name :email :disabled true - :help-icon i/at :label (tr "dashboard.your-email")}] [:div {:class (stl/css :options)}