♻️ Refactor fm/submit-button component

This commit is contained in:
Andrey Antukh 2023-07-20 10:57:56 +02:00
parent 9b9c5822d1
commit 98091057f9
15 changed files with 114 additions and 69 deletions

View file

@ -177,12 +177,12 @@
[:div.buttons-stack [:div.buttons-stack
(when (or (contains? cf/flags :login) (when (or (contains? cf/flags :login)
(contains? cf/flags :login-with-password)) (contains? cf/flags :login-with-password))
[:& fm/submit-button [:> fm/submit-button*
{:label (tr "auth.login-submit") {:label (tr "auth.login-submit")
:data-test "login-submit"}]) :data-test "login-submit"}])
(when (contains? cf/flags :login-with-ldap) (when (contains? cf/flags :login-with-ldap)
[:& fm/submit-button [:> fm/submit-button*
{:label (tr "auth.login-with-ldap-submit") {:label (tr "auth.login-with-ldap-submit")
:on-click on-submit-ldap}])]]])) :on-click on-submit-ldap}])]]]))

View file

@ -72,7 +72,7 @@
:name :password-2 :name :password-2
:label (tr "auth.confirm-password")}]] :label (tr "auth.confirm-password")}]]
[:& fm/submit-button [:> fm/submit-button*
{:label (tr "auth.recovery-submit")}]])) {:label (tr "auth.recovery-submit")}]]))
;; --- Recovery Request Page ;; --- Recovery Request Page

View file

@ -32,7 +32,7 @@
(mf/defc recovery-form (mf/defc recovery-form
[{:keys [on-success-callback] :as props}] [{:keys [on-success-callback] :as props}]
(let [form (fm/use-form :spec ::recovery-request-form (let [form (fm/use-form :spec ::recovery-request-form
:validators [handle-error-messages] :validators [handle-error-messages]
:initial {}) :initial {})
submitted (mf/use-state false) submitted (mf/use-state false)
@ -82,7 +82,7 @@
:help-icon i/at :help-icon i/at
:type "text"}]] :type "text"}]]
[:& fm/submit-button [:> fm/submit-button*
{:label (tr "auth.recovery-request-submit") {:label (tr "auth.recovery-request-submit")
:data-test "recovery-resquest-submit"}]])) :data-test "recovery-resquest-submit"}]]))

View file

@ -124,7 +124,7 @@
:label (tr "auth.password") :label (tr "auth.password")
:type "password"}]] :type "password"}]]
[:& fm/submit-button [:> fm/submit-button*
{:label (tr "auth.register-submit") {:label (tr "auth.register-submit")
:disabled @submitted? :disabled @submitted?
:data-test "register-form-submit"}]])) :data-test "register-form-submit"}]]))
@ -259,7 +259,7 @@
[:span ",\u00A0"] [:span ",\u00A0"]
[:a {:href "https://penpot.app/privacy" :target "_blank"} (tr "auth.privacy-policy")]]]) [:a {:href "https://penpot.app/privacy" :target "_blank"} (tr "auth.privacy-policy")]]])
[:& fm/submit-button [:> fm/submit-button*
{:label (tr "auth.register-submit") {:label (tr "auth.register-submit")
:disabled @submitted?}]])) :disabled @submitted?}]]))

View file

@ -236,56 +236,98 @@
i/arrow-slide]]])) i/arrow-slide]]]))
(mf/defc radio-buttons (mf/defc radio-buttons
[{:keys [name options form trim on-change-value] :as props}] {::mf/wrap-props false}
(let [form (or form (mf/use-ctx form-ctx)) [props]
value (get-in @form [:data name] "") (let [form (or (unchecked-get props "form")
on-change-value (or on-change-value (constantly nil)) (mf/use-ctx form-ctx))
on-change (fn [event] name (unchecked-get props "name")
(let [value (-> event dom/get-target dom/get-value)]
(swap! form assoc-in [:touched name] true)
(fm/on-input-change form name value trim)
(on-change-value name value)))]
[:div.custom-radio
(for [item options]
(let [id (str/ffmt "%-%" name (:value item))
image (:image item)]
[:div.input-radio {:key id :class (when image "with-image")}
[:input {:on-change on-change
:type "radio"
:id id
:name name
:value (:value item)
:checked (= value (:value item))}]
[:label {:for id
:style {:background-image (when image (str/ffmt "url(%)" image))}
:class (when image "with-image")}
(:label item)]]))]))
(mf/defc submit-button current-value (or (dm/get-in @form [:data name] "")
[{:keys [label form on-click disabled data-test] :as props}] (unchecked-get props "value"))
(let [form (or form (mf/use-ctx form-ctx))] on-change (unchecked-get props "on-change")
[:input.btn-primary.btn-large options (unchecked-get props "options")
{:name "submit" trim? (unchecked-get props "trim")
:class (when (or (not (:valid @form)) (true? disabled)) "btn-disabled") encode-fn (d/nilv (unchecked-get props "encode-fn") identity)
:disabled (or (not (:valid @form)) (true? disabled)) decode-fn (d/nilv (unchecked-get props "decode-fn") identity)
:tab-index "0"
:on-click on-click on-change'
:on-key-down (fn [event] (mf/use-fn
(when (kbd/enter? event) (mf/deps on-change form name)
(on-click))) (fn [event]
:value label (let [value (-> event dom/get-target dom/get-value decode-fn)]
:data-test data-test (when (some? form)
:type "submit"}])) (swap! form assoc-in [:touched name] true)
(fm/on-input-change form name value trim?))
(when (fn? on-change)
(on-change name value)))))]
[:div.custom-radio
(for [{:keys [image value label]} options]
(let [image? (some? image)
value' (encode-fn value)
key (str/ffmt "%-%" name value')]
[:div.input-radio {:key key :class (when image? "with-image")}
[:input {:on-change on-change'
:type "radio"
:id key
:name name
:value value'
:checked (= value current-value)}]
[:label {:for key
:style {:background-image (when image? (str/ffmt "url(%)" image))}
:class (when image? "with-image")}
label]]))]))
(mf/defc submit-button*
{::mf/wrap-props false}
[props]
(let [form (or (unchecked-get props "form")
(mf/use-ctx form-ctx))
label (unchecked-get props "label")
on-click (unchecked-get props "onClick")
children (unchecked-get props "children")
class (d/nilv (unchecked-get props "className") "btn-primary btn-large")
name (d/nilv (unchecked-get props "name") "submit")
disabled? (or (and (some? form) (not (:valid @form)))
(true? (unchecked-get props "disabled")))
klass (dm/str class " " (if disabled? "btn-disabled" ""))
on-key-down
(mf/use-fn
(mf/deps on-click)
(fn [event]
(when (and (kbd/enter? event) (fn? on-click))
(on-click event))))
props (-> (obj/clone props)
(obj/unset! "children")
(obj/set! "disabled" disabled?)
(obj/set! "onKeyDown" on-key-down)
(obj/set! "name" name)
(obj/set! "label" mf/undefined)
(obj/set! "className" klass)
(obj/set! "type" "submit"))]
[:> "button" props
(if (some? children)
children
[:span label])]))
(mf/defc form (mf/defc form
[{:keys [on-submit form children class] :as props}] {::mf/wrap-props false}
(let [on-submit (or on-submit (constantly nil))] [{:keys [on-submit form children class]}]
(let [on-submit' (mf/use-fn
(fn [event]
(dom/prevent-default event)
(when (fn? on-submit)
(on-submit form event))))]
[:& (mf/provider form-ctx) {:value form} [:& (mf/provider form-ctx) {:value form}
[:form {:class class [:form {:class class :on-submit on-submit'} children]]))
:on-submit (fn [event]
(dom/prevent-default event)
(on-submit form event))}
children]]))
(defn- conj-dedup (defn- conj-dedup
"A helper that adds item into a vector and removes possible "A helper that adds item into a vector and removes possible

View file

@ -185,9 +185,10 @@
:on-submit on-submit}]] :on-submit on-submit}]]
[:div.action-buttons [:div.action-buttons
[:& fm/submit-button {:label (tr "modals.invite-member-confirm.accept") [:> fm/submit-button*
:disabled (and (boolean (some current-data-emails current-members-emails)) {:label (tr "modals.invite-member-confirm.accept")
(empty? (remove current-members-emails current-data-emails)))}]]]])) :disabled (and (boolean (some current-data-emails current-members-emails))
(empty? (remove current-members-emails current-data-emails)))}]]]]))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; MEMBERS SECTION ;; MEMBERS SECTION
@ -814,7 +815,7 @@
{:type "button" {:type "button"
:value (tr "labels.cancel") :value (tr "labels.cancel")
:on-click #(modal/hide!)}] :on-click #(modal/hide!)}]
[:& fm/submit-button [:> fm/submit-button*
{:label (if webhook {:label (if webhook
(tr "modals.edit-webhook.submit-label") (tr "modals.edit-webhook.submit-label")
(tr "modals.create-webhook.submit-label"))}]]]]]])) (tr "modals.create-webhook.submit-label"))}]]]]]]))

View file

@ -95,7 +95,7 @@
[:div.modal-footer [:div.modal-footer
[:div.action-buttons [:div.action-buttons
[:& fm/submit-button [:> fm/submit-button*
{:label (if team {:label (if team
(tr "labels.update-team") (tr "labels.update-team")
(tr "labels.create-team"))}]]]]]])) (tr "labels.create-team"))}]]]]]]))

View file

@ -26,7 +26,7 @@
children children
[:div.buttons [:div.buttons
[:div.step-next [:div.step-next
[:& fm/submit-button [:> fm/submit-button*
{:label (if (< step 4) (tr "questions.next") (tr "questions.start")) {:label (if (< step 4) (tr "questions.next") (tr "questions.start"))
:class "step-next"}]] :class "step-next"}]]
@ -114,7 +114,7 @@
{:label (tr "questions.never-used-a-tool") :value "never-used-a-tool" :image "images/form/never-used.png"} {:label (tr "questions.never-used-a-tool") :value "never-used-a-tool" :image "images/form/never-used.png"}
{:label (tr "questions.other") :value "other"}] {:label (tr "questions.other") :value "other"}]
:name :experience-design-tool :name :experience-design-tool
:on-change-value on-design-tool-change}] :on-change on-design-tool-change}]
[:div.other [:div.other
[:label (tr "questions.other")] [:label (tr "questions.other")]
[:& fm/input {:name :experience-design-tool-other :label (tr "questions.other") :disabled (not= experience-design-tool "other")}]]])) [:& fm/input {:name :experience-design-tool-other :label (tr "questions.other") :disabled (not= experience-design-tool "other")}]]]))
@ -152,7 +152,7 @@
{:label (tr "questions.student-teacher") :value "student-teacher"} {:label (tr "questions.student-teacher") :value "student-teacher"}
{:label (tr "questions.other") :value "other"}] {:label (tr "questions.other") :value "other"}]
:name :role :name :role
:on-change-value on-role-change}] :on-change on-role-change}]
[:div.other [:div.other
[:label (tr "questions.other")] [:label (tr "questions.other")]
[:& fm/input {:name :role-other :label (tr "questions.other") :disabled (not= role "other")}]] [:& fm/input {:name :role-other :label (tr "questions.other") :disabled (not= role "other")}]]

View file

@ -87,7 +87,7 @@
:name :name :name :name
:label (tr "onboarding.choice.team-up.create-team-placeholder")}] :label (tr "onboarding.choice.team-up.create-team-placeholder")}]
[:& fm/submit-button [:> fm/submit-button*
{:label (tr "labels.continue")}]] {:label (tr "labels.continue")}]]
[:button.skip-action {:on-click on-skip} (tr "onboarding.choice.team-up.create-later")]] [:button.skip-action {:on-click on-skip} (tr "onboarding.choice.team-up.create-later")]]
@ -199,8 +199,9 @@
:name name :name name
:step 2}))} :step 2}))}
(tr "labels.back")] (tr "labels.back")]
[:& fm/submit-button [:> fm/submit-button*
{:label (tr "onboarding.choice.team-up.invite-members-submit")}]] {:label (tr "onboarding.choice.team-up.invite-members-submit")}]]
[:div.skip-action [:div.skip-action
{:on-click on-skip} {:on-click on-skip}
[:div.action (tr "onboarding.choice.team-up.invite-members-skip")]]]] [:div.action (tr "onboarding.choice.team-up.invite-members-skip")]]]]

View file

@ -166,7 +166,7 @@
{:type "button" {:type "button"
:value (tr "labels.cancel") :value (tr "labels.cancel")
:on-click #(modal/hide!)}] :on-click #(modal/hide!)}]
[:& fm/submit-button [:> fm/submit-button*
{:label (tr "modals.create-access-token.submit-label")}]])]]]]])) {:label (tr "modals.create-access-token.submit-label")}]])]]]]]))
(mf/defc access-tokens-hero (mf/defc access-tokens-hero

View file

@ -129,7 +129,7 @@
[:div.modal-footer [:div.modal-footer
[:div.action-buttons {:data-test "change-email-submit"} [:div.action-buttons {:data-test "change-email-submit"}
[:& fm/submit-button [:> fm/submit-button*
{:label (tr "modals.change-email.submit")}]]]]]])) {:label (tr "modals.change-email.submit")}]]]]]]))

View file

@ -76,7 +76,7 @@
:name :content :name :content
:rows 5}]] :rows 5}]]
[:& fm/submit-button [:> fm/submit-button*
{:label (if @loading (tr "labels.sending") (tr "labels.send")) {:label (if @loading (tr "labels.sending") (tr "labels.send"))
:disabled @loading}] :disabled @loading}]

View file

@ -35,6 +35,7 @@
(st/emit! (du/update-profile (with-meta data mdata))))) (st/emit! (du/update-profile (with-meta data mdata)))))
(mf/defc options-form (mf/defc options-form
{::mf/wrap-props false}
[] []
(let [profile (mf/deref refs/profile) (let [profile (mf/deref refs/profile)
initial (mf/with-memo [profile] initial (mf/with-memo [profile]
@ -66,7 +67,7 @@
:options [{:label "Penpot Dark (default)" :value "default"} :options [{:label "Penpot Dark (default)" :value "default"}
{:label "Penpot Light" :value "light"}] {:label "Penpot Light" :value "light"}]
:data-test "setting-theme"}]]) :data-test "setting-theme"}]])
[:& fm/submit-button [:> fm/submit-button*
{:label (tr "dashboard.update-settings") {:label (tr "dashboard.update-settings")
:data-test "submit-lang-change"}]])) :data-test "submit-lang-change"}]]))

View file

@ -98,7 +98,7 @@
:name :password-2 :name :password-2
:label (t locale "labels.confirm-password")}]] :label (t locale "labels.confirm-password")}]]
[:& fm/submit-button [:> fm/submit-button*
{:label (t locale "dashboard.update-settings") {:label (t locale "dashboard.update-settings")
:data-test "submit-password"}]])) :data-test "submit-password"}]]))

View file

@ -69,7 +69,7 @@
[:a {:on-click #(modal/show! :change-email {})} [:a {:on-click #(modal/show! :change-email {})}
(tr "dashboard.change-email")]]]] (tr "dashboard.change-email")]]]]
[:& fm/submit-button [:> fm/submit-button*
{:label (tr "dashboard.save-settings") {:label (tr "dashboard.save-settings")
:disabled (empty? (:touched @form))}] :disabled (empty? (:touched @form))}]