mirror of
https://github.com/penpot/penpot.git
synced 2025-06-11 14:11:38 +02:00
💄 Refactor usability of input fields
This commit is contained in:
parent
8c49d11026
commit
b7bf7c8baf
2 changed files with 104 additions and 86 deletions
|
@ -86,21 +86,18 @@ textarea {
|
||||||
.custom-input {
|
.custom-input {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
position: relative;
|
||||||
label {
|
|
||||||
font-size: $fs10;
|
|
||||||
color: $color-gray-30;
|
|
||||||
}
|
|
||||||
|
|
||||||
input {
|
input {
|
||||||
|
background-color: $color-white;
|
||||||
|
border-radius: 2px;
|
||||||
|
border: 1px solid $color-gray-20;
|
||||||
color: $color-gray-60;
|
color: $color-gray-60;
|
||||||
font-size: $fs12;
|
font-size: $fs12;
|
||||||
|
height: 40px;
|
||||||
|
margin: 0;
|
||||||
|
padding: 15px 15px 0 15px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
border: 0px;
|
|
||||||
padding: 0px;
|
|
||||||
margin: 0px;
|
|
||||||
background-color: transparent;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Makes the background for autocomplete white
|
// Makes the background for autocomplete white
|
||||||
|
@ -111,38 +108,77 @@ textarea {
|
||||||
-webkit-box-shadow: 0 0 0 30px $color-white inset !important;
|
-webkit-box-shadow: 0 0 0 30px $color-white inset !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.input-container {
|
label {
|
||||||
display: flex;
|
font-size: $fs10;
|
||||||
flex-direction: row;
|
color: $color-gray-30;
|
||||||
|
position: absolute;
|
||||||
|
left: 15px;
|
||||||
|
top: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
background-color: $color-white;
|
&.invalid {
|
||||||
border-radius: 2px;
|
input {
|
||||||
border: 1px solid $color-gray-20;
|
|
||||||
height: 40px;
|
|
||||||
padding-left: 15px;
|
|
||||||
padding-right: 15px;
|
|
||||||
|
|
||||||
&.invalid {
|
|
||||||
border-color: $color-danger;
|
border-color: $color-danger;
|
||||||
label {
|
|
||||||
color: $color-danger;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
label {
|
||||||
|
color: $color-danger;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
&.valid {
|
&.valid {
|
||||||
|
input {
|
||||||
border-color: $color-success;
|
border-color: $color-success;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
&.focus {
|
&.focus {
|
||||||
|
input {
|
||||||
border-color: $color-gray-60;
|
border-color: $color-gray-60;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
&.disabled {
|
&.disabled {
|
||||||
|
input {
|
||||||
background-color: lighten($color-gray-10, 5%);
|
background-color: lighten($color-gray-10, 5%);
|
||||||
user-select: none;
|
user-select: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.empty {
|
||||||
|
input {
|
||||||
|
padding-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
label {
|
||||||
|
clip: rect(0 0 0 0);
|
||||||
|
height: 1px;
|
||||||
|
margin: -1px;
|
||||||
|
overflow: hidden;
|
||||||
|
padding: 0;
|
||||||
|
width: 1px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.with-icon {
|
||||||
|
input {
|
||||||
|
padding-right: 50px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.help-icon {
|
||||||
|
position: absolute;
|
||||||
|
right: 15px;
|
||||||
|
top: 12px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
svg {
|
||||||
|
fill: $color-gray-30;
|
||||||
|
width: 15px;
|
||||||
|
height: 15px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.hint {
|
.hint {
|
||||||
padding: 4px;
|
padding: 4px;
|
||||||
font-size: $fs10;
|
font-size: $fs10;
|
||||||
|
@ -153,28 +189,6 @@ textarea {
|
||||||
padding: 4px;
|
padding: 4px;
|
||||||
font-size: $fs10;
|
font-size: $fs10;
|
||||||
}
|
}
|
||||||
|
|
||||||
.main-content {
|
|
||||||
flex-grow: 1;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: center;
|
|
||||||
padding-top: 6px;
|
|
||||||
padding-bottom: 6px;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
.help-icon {
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
padding-left: 10px;
|
|
||||||
svg {
|
|
||||||
fill: $color-gray-30;
|
|
||||||
width: 15px;
|
|
||||||
height: 15px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.custom-select {
|
.custom-select {
|
||||||
|
|
|
@ -23,20 +23,36 @@
|
||||||
|
|
||||||
(mf/defc input
|
(mf/defc input
|
||||||
[{:keys [type label help-icon disabled name form hint] :as props}]
|
[{:keys [type label help-icon disabled name form hint] :as props}]
|
||||||
(let [form (mf/use-ctx form-ctx)
|
(let [form (mf/use-ctx form-ctx)
|
||||||
|
|
||||||
type' (mf/use-state type)
|
type' (mf/use-state type)
|
||||||
focus? (mf/use-state false)
|
focus? (mf/use-state false)
|
||||||
locale (mf/deref i18n/locale)
|
locale (mf/deref i18n/locale)
|
||||||
|
|
||||||
touched? (get-in form [:touched name])
|
touched? (get-in form [:touched name])
|
||||||
error (get-in form [:errors name])
|
error (get-in form [:errors name])
|
||||||
|
|
||||||
|
value (get-in form [:data name] "")
|
||||||
|
|
||||||
|
help-icon' (cond
|
||||||
|
(and (= type "password")
|
||||||
|
(= @type' "password"))
|
||||||
|
i/eye
|
||||||
|
|
||||||
|
(and (= type "password")
|
||||||
|
(= @type' "text"))
|
||||||
|
i/eye-closed
|
||||||
|
|
||||||
|
:else
|
||||||
|
help-icon)
|
||||||
|
|
||||||
klass (dom/classnames
|
klass (dom/classnames
|
||||||
:focus @focus?
|
:focus @focus?
|
||||||
:valid (and touched? (not error))
|
:valid (and touched? (not error))
|
||||||
:invalid (and touched? error)
|
:invalid (and touched? error)
|
||||||
:disabled disabled)
|
:disabled disabled
|
||||||
|
:empty (str/empty? value)
|
||||||
|
:with-icon (not (nil? help-icon')))
|
||||||
|
|
||||||
swap-text-password
|
swap-text-password
|
||||||
(fn []
|
(fn []
|
||||||
|
@ -54,8 +70,6 @@
|
||||||
(when-not (get-in form [:touched name])
|
(when-not (get-in form [:touched name])
|
||||||
(swap! form assoc-in [:touched name] true)))
|
(swap! form assoc-in [:touched name] true)))
|
||||||
|
|
||||||
value (get-in form [:data name] "")
|
|
||||||
|
|
||||||
props (-> props
|
props (-> props
|
||||||
(dissoc :help-icon :form)
|
(dissoc :help-icon :form)
|
||||||
(assoc :value value
|
(assoc :value value
|
||||||
|
@ -67,32 +81,22 @@
|
||||||
(obj/clj->props))]
|
(obj/clj->props))]
|
||||||
|
|
||||||
[:div.field.custom-input
|
[:div.field.custom-input
|
||||||
[:div.input-container {:class klass}
|
{:class klass}
|
||||||
[:div.main-content
|
[:*
|
||||||
(when-not (str/empty? value)
|
[:label label]
|
||||||
[:label label])
|
[:> :input props]
|
||||||
[:> :input props]]
|
(when help-icon'
|
||||||
[:div.help-icon
|
[:div.help-icon
|
||||||
{:style {:cursor "pointer"}
|
{:style {:cursor "pointer"}
|
||||||
:on-click (when (= "password" type)
|
:on-click (when (= "password" type)
|
||||||
swap-text-password)}
|
swap-text-password)}
|
||||||
(cond
|
help-icon'])
|
||||||
(and (= type "password")
|
(cond
|
||||||
(= @type' "password"))
|
(and touched? (:message error))
|
||||||
i/eye
|
[:span.error (t locale (:message error))]
|
||||||
|
|
||||||
(and (= type "password")
|
(string? hint)
|
||||||
(= @type' "text"))
|
[:span.hint hint])]]))
|
||||||
i/eye-closed
|
|
||||||
|
|
||||||
:else
|
|
||||||
help-icon)]]
|
|
||||||
(cond
|
|
||||||
(and touched? (:message error))
|
|
||||||
[:span.error (t locale (:message error))]
|
|
||||||
|
|
||||||
(string? hint)
|
|
||||||
[:span.hint hint])]))
|
|
||||||
|
|
||||||
(mf/defc select
|
(mf/defc select
|
||||||
[{:keys [options label name form default]
|
[{:keys [options label name form default]
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue