diff --git a/backend/resources/app/email/change-email/en.html b/backend/resources/app/email/change-email/en.html index fa021f55ee..238f9f401e 100644 --- a/backend/resources/app/email/change-email/en.html +++ b/backend/resources/app/email/change-email/en.html @@ -122,7 +122,7 @@ - @@ -254,4 +254,4 @@ - \ No newline at end of file + diff --git a/backend/resources/app/email/comment-mention/en.html b/backend/resources/app/email/comment-mention/en.html index d628c96998..74920763bd 100644 --- a/backend/resources/app/email/comment-mention/en.html +++ b/backend/resources/app/email/comment-mention/en.html @@ -122,7 +122,7 @@ - diff --git a/backend/resources/app/email/comment-notification/en.html b/backend/resources/app/email/comment-notification/en.html index 595c6b53da..ee65070346 100644 --- a/backend/resources/app/email/comment-notification/en.html +++ b/backend/resources/app/email/comment-notification/en.html @@ -122,7 +122,7 @@ - diff --git a/backend/resources/app/email/comment-thread/en.html b/backend/resources/app/email/comment-thread/en.html index 8676a35291..690f723280 100644 --- a/backend/resources/app/email/comment-thread/en.html +++ b/backend/resources/app/email/comment-thread/en.html @@ -122,7 +122,7 @@ - diff --git a/backend/resources/app/email/includes/footer.html b/backend/resources/app/email/includes/footer.html index 4581ff37a6..167a4cc6ab 100644 --- a/backend/resources/app/email/includes/footer.html +++ b/backend/resources/app/email/includes/footer.html @@ -29,10 +29,8 @@ style="vertical-align:top;" width="100%"> -
- Penpot is the first Open Source design and prototyping platform meant for - cross-domain teams. +
+ Penpot is the open-source design platform for teams that need scalable collaboration.
@@ -100,9 +98,9 @@ - + @@ -126,9 +124,9 @@ - + @@ -152,9 +150,9 @@ - + @@ -178,10 +176,36 @@ - + + + + + + + + + + + + + +
+ + + + +
+ @@ -205,9 +229,9 @@
- + @@ -231,10 +255,36 @@
- + +
+
+ + + + diff --git a/backend/resources/app/email/invite-to-team/en.html b/backend/resources/app/email/invite-to-team/en.html index 31d1ddf4a3..9ebc59231f 100644 --- a/backend/resources/app/email/invite-to-team/en.html +++ b/backend/resources/app/email/invite-to-team/en.html @@ -122,7 +122,7 @@ diff --git a/backend/resources/app/email/join-team/en.html b/backend/resources/app/email/join-team/en.html index 8f88a125b0..7df193b444 100644 --- a/backend/resources/app/email/join-team/en.html +++ b/backend/resources/app/email/join-team/en.html @@ -122,7 +122,7 @@ @@ -241,4 +241,4 @@ - \ No newline at end of file + diff --git a/backend/resources/app/email/password-recovery/en.html b/backend/resources/app/email/password-recovery/en.html index 37693942d3..ded10cf78f 100644 --- a/backend/resources/app/email/password-recovery/en.html +++ b/backend/resources/app/email/password-recovery/en.html @@ -122,7 +122,7 @@ @@ -249,4 +249,4 @@ - \ No newline at end of file + diff --git a/backend/resources/app/email/register/en.html b/backend/resources/app/email/register/en.html index 8ee3b855a9..6a5062b4de 100644 --- a/backend/resources/app/email/register/en.html +++ b/backend/resources/app/email/register/en.html @@ -122,7 +122,7 @@ @@ -179,15 +179,21 @@ + + + @@ -218,7 +224,7 @@
+ + +
+ + @@ -320,4 +370,4 @@
- \ No newline at end of file + diff --git a/backend/resources/app/email/invite-to-org/en.html b/backend/resources/app/email/invite-to-org/en.html index babfca5a9e..ce3a9846b3 100644 --- a/backend/resources/app/email/invite-to-org/en.html +++ b/backend/resources/app/email/invite-to-org/en.html @@ -122,7 +122,7 @@
-
-
-
-
-
- Hello {{name|abbreviate:25}}!
+ Hi {{name|abbreviate:25}},
- Thanks for signing up for your Penpot account! Please verify your email using the link below and - get started building mockups and prototypes today!
+ Welcome to Penpot! +
+
+ Please verify your email to get started with your first design and collaboration.
- The Penpot team.
+ The Penpot team
@@ -241,4 +247,4 @@
- \ No newline at end of file + diff --git a/backend/resources/app/email/register/en.subj b/backend/resources/app/email/register/en.subj index 4b49d94ba3..c9aa634a81 100644 --- a/backend/resources/app/email/register/en.subj +++ b/backend/resources/app/email/register/en.subj @@ -1 +1 @@ -Verify email. +Verify your Penpot account diff --git a/backend/resources/app/email/register/en.txt b/backend/resources/app/email/register/en.txt index c38454ccde..30b91be484 100644 --- a/backend/resources/app/email/register/en.txt +++ b/backend/resources/app/email/register/en.txt @@ -1,9 +1,11 @@ -Hello {{name|abbreviate:25}}! +Hi {{name|abbreviate:25}}, -Thanks for signing up for your Penpot account! Please verify your email using the -link below and get started building mockups and prototypes today! +Welcome to Penpot! + +Please verify your email to get started with your first design and collaboration. {{ public-uri }}/#/auth/verify-token?token={{token}} Enjoy! -The Penpot team. + +The Penpot team diff --git a/backend/resources/app/email/renewal-notice/en.html b/backend/resources/app/email/renewal-notice/en.html index 2b6b7a04ad..81d76a8b8e 100644 --- a/backend/resources/app/email/renewal-notice/en.html +++ b/backend/resources/app/email/renewal-notice/en.html @@ -122,7 +122,7 @@ - diff --git a/backend/resources/app/email/request-file-access-yourpenpot-view/en.html b/backend/resources/app/email/request-file-access-yourpenpot-view/en.html index e80d46488a..57f0bbb781 100644 --- a/backend/resources/app/email/request-file-access-yourpenpot-view/en.html +++ b/backend/resources/app/email/request-file-access-yourpenpot-view/en.html @@ -122,7 +122,7 @@ - diff --git a/backend/resources/app/email/request-file-access-yourpenpot/en.html b/backend/resources/app/email/request-file-access-yourpenpot/en.html index 596e59bf32..ca0b00ee27 100644 --- a/backend/resources/app/email/request-file-access-yourpenpot/en.html +++ b/backend/resources/app/email/request-file-access-yourpenpot/en.html @@ -122,7 +122,7 @@ - diff --git a/backend/resources/app/email/request-file-access/en.html b/backend/resources/app/email/request-file-access/en.html index bda16c658d..5887027350 100644 --- a/backend/resources/app/email/request-file-access/en.html +++ b/backend/resources/app/email/request-file-access/en.html @@ -122,7 +122,7 @@ - diff --git a/backend/resources/app/email/request-team-access/en.html b/backend/resources/app/email/request-team-access/en.html index b8045fa1e3..7d279f505b 100644 --- a/backend/resources/app/email/request-team-access/en.html +++ b/backend/resources/app/email/request-team-access/en.html @@ -122,7 +122,7 @@ - diff --git a/frontend/resources/images/email/logo-bluesky.svg b/frontend/resources/images/email/logo-bluesky.svg new file mode 100644 index 0000000000..3f7611d162 --- /dev/null +++ b/frontend/resources/images/email/logo-bluesky.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/frontend/resources/images/email/logo-github.png b/frontend/resources/images/email/logo-github.png deleted file mode 100644 index e3d3215af3..0000000000 Binary files a/frontend/resources/images/email/logo-github.png and /dev/null differ diff --git a/frontend/resources/images/email/logo-github.svg b/frontend/resources/images/email/logo-github.svg new file mode 100644 index 0000000000..5a4067f804 --- /dev/null +++ b/frontend/resources/images/email/logo-github.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/frontend/resources/images/email/logo-instagram.png b/frontend/resources/images/email/logo-instagram.png deleted file mode 100644 index 3b94e53a29..0000000000 Binary files a/frontend/resources/images/email/logo-instagram.png and /dev/null differ diff --git a/frontend/resources/images/email/logo-instagram.svg b/frontend/resources/images/email/logo-instagram.svg new file mode 100644 index 0000000000..5e2c48e404 --- /dev/null +++ b/frontend/resources/images/email/logo-instagram.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/frontend/resources/images/email/logo-linkedin.png b/frontend/resources/images/email/logo-linkedin.png deleted file mode 100644 index ee24f90dbd..0000000000 Binary files a/frontend/resources/images/email/logo-linkedin.png and /dev/null differ diff --git a/frontend/resources/images/email/logo-linkedin.svg b/frontend/resources/images/email/logo-linkedin.svg new file mode 100644 index 0000000000..8185b09394 --- /dev/null +++ b/frontend/resources/images/email/logo-linkedin.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/frontend/resources/images/email/logo-mastodon.png b/frontend/resources/images/email/logo-mastodon.png deleted file mode 100644 index f0a14cf61f..0000000000 Binary files a/frontend/resources/images/email/logo-mastodon.png and /dev/null differ diff --git a/frontend/resources/images/email/logo-mastodon.svg b/frontend/resources/images/email/logo-mastodon.svg new file mode 100644 index 0000000000..829b2d481b --- /dev/null +++ b/frontend/resources/images/email/logo-mastodon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/frontend/resources/images/email/logo-penpot.svg b/frontend/resources/images/email/logo-penpot.svg new file mode 100644 index 0000000000..6439292bd2 --- /dev/null +++ b/frontend/resources/images/email/logo-penpot.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/frontend/resources/images/email/logo-reddit.svg b/frontend/resources/images/email/logo-reddit.svg new file mode 100644 index 0000000000..a3e11ee3c8 --- /dev/null +++ b/frontend/resources/images/email/logo-reddit.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/frontend/resources/images/email/logo-taiga.png b/frontend/resources/images/email/logo-taiga.png deleted file mode 100644 index e604e8b15a..0000000000 Binary files a/frontend/resources/images/email/logo-taiga.png and /dev/null differ diff --git a/frontend/resources/images/email/logo-twitter.png b/frontend/resources/images/email/logo-twitter.png deleted file mode 100644 index 4860be5d82..0000000000 Binary files a/frontend/resources/images/email/logo-twitter.png and /dev/null differ diff --git a/frontend/resources/images/email/logo-uxbox.png b/frontend/resources/images/email/logo-uxbox.png deleted file mode 100644 index 8b3a078296..0000000000 Binary files a/frontend/resources/images/email/logo-uxbox.png and /dev/null differ diff --git a/frontend/resources/images/email/logo-x.png b/frontend/resources/images/email/logo-x.png deleted file mode 100644 index cdaf322475..0000000000 Binary files a/frontend/resources/images/email/logo-x.png and /dev/null differ diff --git a/frontend/resources/images/email/logo-x.svg b/frontend/resources/images/email/logo-x.svg new file mode 100644 index 0000000000..bfa2cf3093 --- /dev/null +++ b/frontend/resources/images/email/logo-x.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/frontend/resources/images/email/logo-youtube.svg b/frontend/resources/images/email/logo-youtube.svg new file mode 100644 index 0000000000..3db099e43d --- /dev/null +++ b/frontend/resources/images/email/logo-youtube.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/frontend/resources/images/email/uxbox-title.png b/frontend/resources/images/email/uxbox-title.png deleted file mode 100644 index 18a878202c..0000000000 Binary files a/frontend/resources/images/email/uxbox-title.png and /dev/null differ diff --git a/frontend/resources/images/form/Design.png b/frontend/resources/images/form/Design.png deleted file mode 100644 index ae1e28ab72..0000000000 Binary files a/frontend/resources/images/form/Design.png and /dev/null differ diff --git a/frontend/resources/images/form/Prototype.png b/frontend/resources/images/form/Prototype.png deleted file mode 100644 index 508d43e1d3..0000000000 Binary files a/frontend/resources/images/form/Prototype.png and /dev/null differ diff --git a/frontend/resources/images/form/components.png b/frontend/resources/images/form/components.png deleted file mode 100644 index e1817a6a96..0000000000 Binary files a/frontend/resources/images/form/components.png and /dev/null differ diff --git a/frontend/resources/images/form/design-and-dev.png b/frontend/resources/images/form/design-and-dev.png deleted file mode 100644 index b66bddc793..0000000000 Binary files a/frontend/resources/images/form/design-and-dev.png and /dev/null differ diff --git a/frontend/resources/images/form/never-used.png b/frontend/resources/images/form/never-used.png deleted file mode 100644 index f45d6cf2db..0000000000 Binary files a/frontend/resources/images/form/never-used.png and /dev/null differ diff --git a/frontend/resources/images/form/slide-1-help-us-know-you.svg b/frontend/resources/images/form/slide-1-help-us-know-you.svg new file mode 100644 index 0000000000..0064fdbfe7 --- /dev/null +++ b/frontend/resources/images/form/slide-1-help-us-know-you.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/frontend/resources/images/form/adobe-xd.png b/frontend/resources/images/form/slide-2-adobe-xd.png similarity index 100% rename from frontend/resources/images/form/adobe-xd.png rename to frontend/resources/images/form/slide-2-adobe-xd.png diff --git a/frontend/resources/images/form/canva.png b/frontend/resources/images/form/slide-2-canva.png similarity index 100% rename from frontend/resources/images/form/canva.png rename to frontend/resources/images/form/slide-2-canva.png diff --git a/frontend/resources/images/form/figma.png b/frontend/resources/images/form/slide-2-figma.png similarity index 100% rename from frontend/resources/images/form/figma.png rename to frontend/resources/images/form/slide-2-figma.png diff --git a/frontend/resources/images/form/invision.png b/frontend/resources/images/form/slide-2-invision.png similarity index 100% rename from frontend/resources/images/form/invision.png rename to frontend/resources/images/form/slide-2-invision.png diff --git a/frontend/resources/images/form/sketch.png b/frontend/resources/images/form/slide-2-sketch.png similarity index 100% rename from frontend/resources/images/form/sketch.png rename to frontend/resources/images/form/slide-2-sketch.png diff --git a/frontend/resources/images/form/slide-3-code-from-design.svg b/frontend/resources/images/form/slide-3-code-from-design.svg new file mode 100644 index 0000000000..92b4449f43 --- /dev/null +++ b/frontend/resources/images/form/slide-3-code-from-design.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/frontend/resources/images/form/slide-3-design-app-ui-ux.svg b/frontend/resources/images/form/slide-3-design-app-ui-ux.svg new file mode 100644 index 0000000000..91b59ed564 --- /dev/null +++ b/frontend/resources/images/form/slide-3-design-app-ui-ux.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/frontend/resources/images/form/slide-3-design-systems.svg b/frontend/resources/images/form/slide-3-design-systems.svg new file mode 100644 index 0000000000..8f2b8a2a91 --- /dev/null +++ b/frontend/resources/images/form/slide-3-design-systems.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/frontend/resources/images/form/slide-3-prototyping.svg b/frontend/resources/images/form/slide-3-prototyping.svg new file mode 100644 index 0000000000..4b221bf145 --- /dev/null +++ b/frontend/resources/images/form/slide-3-prototyping.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/frontend/resources/images/form/slide-3-wireframing.svg b/frontend/resources/images/form/slide-3-wireframing.svg new file mode 100644 index 0000000000..0e288e3ec2 --- /dev/null +++ b/frontend/resources/images/form/slide-3-wireframing.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/frontend/resources/images/form/slide-final-team.svg b/frontend/resources/images/form/slide-final-team.svg new file mode 100644 index 0000000000..48f2611188 --- /dev/null +++ b/frontend/resources/images/form/slide-final-team.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/frontend/resources/images/form/templates.png b/frontend/resources/images/form/templates.png deleted file mode 100644 index 3c77a7a0ff..0000000000 Binary files a/frontend/resources/images/form/templates.png and /dev/null differ diff --git a/frontend/resources/images/form/use-for-1.png b/frontend/resources/images/form/use-for-1.png deleted file mode 100644 index 832043178c..0000000000 Binary files a/frontend/resources/images/form/use-for-1.png and /dev/null differ diff --git a/frontend/resources/images/form/use-for-2.jpg b/frontend/resources/images/form/use-for-2.jpg deleted file mode 100644 index 449ab4d9f1..0000000000 Binary files a/frontend/resources/images/form/use-for-2.jpg and /dev/null differ diff --git a/frontend/resources/images/form/use-for-3.jpg b/frontend/resources/images/form/use-for-3.jpg deleted file mode 100644 index 1d8c242d76..0000000000 Binary files a/frontend/resources/images/form/use-for-3.jpg and /dev/null differ diff --git a/frontend/resources/images/form/use-for-4.jpg b/frontend/resources/images/form/use-for-4.jpg deleted file mode 100644 index 140c6539dc..0000000000 Binary files a/frontend/resources/images/form/use-for-4.jpg and /dev/null differ diff --git a/frontend/resources/images/form/uxpin.png b/frontend/resources/images/form/uxpin.png deleted file mode 100644 index bbd155d6a4..0000000000 Binary files a/frontend/resources/images/form/uxpin.png and /dev/null differ diff --git a/frontend/src/app/main/ui/auth/recovery_request.cljs b/frontend/src/app/main/ui/auth/recovery_request.cljs index 1142f774b5..3233df8a30 100644 --- a/frontend/src/app/main/ui/auth/recovery_request.cljs +++ b/frontend/src/app/main/ui/auth/recovery_request.cljs @@ -110,7 +110,7 @@ [:div {:class (stl/css :auth-form-wrapper :register-success)} [:div {:class (stl/css :auth-title-wrapper)} [:h2 {:class (stl/css :auth-title)} - (tr "auth.check-mail")] + (tr "auth.check-email")] [:div {:class (stl/css :notification-text)} (tr "not-found.login.sent-recovery")]] [:div {:class (stl/css :notification-text-email)} email] [:div {:class (stl/css :notification-text)} (tr "not-found.login.sent-recovery-check")]]) diff --git a/frontend/src/app/main/ui/auth/register.cljs b/frontend/src/app/main/ui/auth/register.cljs index d5786e3942..bb8966d12b 100644 --- a/frontend/src/app/main/ui/auth/register.cljs +++ b/frontend/src/app/main/ui/auth/register.cljs @@ -234,8 +234,8 @@ [:div {:class (stl/css :auth-form-wrapper :register-success)} [:div {:class (stl/css :auth-title-wrapper)} [:h2 {:class (stl/css :auth-title)} - (tr "auth.check-mail")] - [:div {:class (stl/css :notification-text)} (tr "auth.verification-email-sent")]] + (tr "auth.check-email")] + [:div {:class (stl/css :notification-text)} (tr "auth.verification-sent-email")]] [:div {:class (stl/css :notification-text-email)} email]])) (mf/defc terms-register* diff --git a/frontend/src/app/main/ui/forms.cljs b/frontend/src/app/main/ui/forms.cljs index 82e072aab9..82b0335008 100644 --- a/frontend/src/app/main/ui/forms.cljs +++ b/frontend/src/app/main/ui/forms.cljs @@ -5,13 +5,18 @@ ;; Copyright (c) KALEIDOS INC Sucursal en España SL (ns app.main.ui.forms + (:require-macros [app.main.style :as stl]) (:require [app.main.ui.ds.buttons.button :refer [button*]] + [app.main.ui.ds.buttons.icon-button :refer [icon-button*]] [app.main.ui.ds.controls.input :refer [input*]] [app.main.ui.ds.controls.select :refer [select*]] + [app.main.ui.ds.foundations.assets.icon :as i] [app.util.dom :as dom] [app.util.forms :as fm] + [app.util.i18n :refer [tr]] [app.util.keyboard :as k] + [cuerdas.core :as str] [rumext.v2 :as mf])) (def context (mf/create-context nil)) @@ -49,8 +54,150 @@ [:> input* props])) +(defn- conj-dedup + "Adds item into a vector and removes possible duplicates." + [coll item] + (into [] (distinct) (conj coll item))) + +(mf/defc form-multi-input* + [{:keys [name trim valid-item-fn caution-item-fn] :rest props}] + (let [form (mf/use-ctx context) + + touched? (and (contains? (:data @form) name) + (get-in @form [:touched name])) + + value (mf/use-state "") + focus? (mf/use-state false) + + items + (mf/use-state + (fn [] + (let [initial (get-in @form [:data name])] + (if (or (vector? initial) (set? initial)) + (mapv (fn [val] + {:text val + :valid (valid-item-fn val) + :caution (caution-item-fn val)}) + initial) + [])))) + + on-focus + (mf/use-fn + #(reset! focus? true)) + + on-change + (mf/use-fn + (fn [event] + (let [content (-> event dom/get-target dom/get-input-value)] + (reset! value content)))) + + on-key-down + (mf/use-fn + (mf/deps @value form name valid-item-fn caution-item-fn trim) + (fn [event] + (let [val (cond-> @value trim str/trim)] + (cond + (or (k/enter? event) (k/comma? event) (k/space? event)) + (do + (dom/prevent-default event) + (dom/stop-propagation event) + (swap! form assoc-in [:touched name] true) + (when (and (valid-item-fn val) (not (str/empty? @value))) + (reset! value "") + (swap! form assoc-in [:touched name] false) + (doseq [v (str/split val #",|\s+")] + (let [v (str/trim v)] + (swap! items conj-dedup {:text v + :valid (valid-item-fn v) + :caution (caution-item-fn v)}))))) + + (and (k/backspace? event) (str/empty? @value)) + (do + (dom/prevent-default event) + (dom/stop-propagation event) + (swap! items (fn [items] + (if (empty? items) items (pop items))))))))) + + on-paste + (mf/use-fn + (fn [event] + (let [paste-data (-> event .-clipboardData (.getData "text"))] + (when (and (string? paste-data) + (re-find #"[,\s]" paste-data)) + (dom/prevent-default event) + (dom/stop-propagation event) + + ;; Mark as touched + (swap! form assoc-in [:touched name] true) + + ;; Split pasted text by commas and/or whitespace, add each valid part + (let [parts (->> (str/split paste-data #",|\s+") + (map str/trim) + (remove str/empty?))] + (doseq [part parts] + (when (valid-item-fn part) + (swap! items conj-dedup {:text part + :valid true + :caution (caution-item-fn part)}))) + + ;; Reset input value and mark as untouched after successful paste + (reset! value "") + (swap! form assoc-in [:touched name] false)))))) + + on-blur + (mf/use-fn + (fn [] + (reset! focus? false) + (when-not (get-in @form [:touched name]) + (swap! form assoc-in [:touched name] true)))) + + on-remove-item + (mf/use-fn + (fn [item] + (swap! items #(filterv (fn [x] (not= x item)) %)))) + + props + (mf/spread-props props {:value @value + :on-change on-change + :on-focus on-focus + :on-blur on-blur + :on-key-down on-key-down + :on-paste on-paste + :hint-type (when (and touched? + (not (str/empty? @value)) + (not (valid-item-fn @value))) "error")})] + + ;; Sync form data whenever items or input value changes. + ;; This ensures the current (unconfirmed) input value is included in the + ;; form data when the user submits without pressing Enter/Space/Comma. + (mf/with-effect [@items @value] + (let [items-text (mapv :text @items) + val (cond-> @value trim str/trim) + combined (if (and (valid-item-fn val) (not (str/empty? val))) + (conj items-text val) + items-text) + data (str/join " " combined)] + (fm/update-input-value! form name data))) + + [:div {:class (stl/css :multi-input)} + [:> input* props] + + (when-let [items-seq (seq @items)] + [:div {:class (stl/css :multi-input-chips)} + (for [item items-seq] + [:div {:class (stl/css :multi-input-chip) + :key (:text item)} + [:span {:class (stl/css :multi-input-chip-text)} + (:text item)] + [:> icon-button* {:variant "ghost" + :class (stl/css :multi-input-chip-icon) + :icon i/close + :icon-size "s" + :aria-label (tr "labels.remove") + :on-click (partial on-remove-item item)}]])])])) + (mf/defc form-select* - [{:keys [name] :as props}] + [{:keys [name] :rest props}] (let [select-name name form (mf/use-ctx context) value (get-in @form [:data select-name] "") diff --git a/frontend/src/app/main/ui/forms.scss b/frontend/src/app/main/ui/forms.scss new file mode 100644 index 0000000000..c576dfcda2 --- /dev/null +++ b/frontend/src/app/main/ui/forms.scss @@ -0,0 +1,43 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. +// +// Copyright (c) KALEIDOS INC Sucursal en España SL + +@use "ds/typography.scss" as t; +@use "ds/_borders.scss" as *; +@use "ds/_sizes.scss" as *; +@use "ds/_utils.scss" as *; + +.multi-input { + display: flex; + flex-direction: column; + gap: var(--sp-s); +} + +.multi-input-chips { + display: flex; + flex-wrap: wrap; + gap: var(--sp-xs); +} + +.multi-input-chip { + display: flex; + align-items: center; + gap: var(--sp-xs); + block-size: $sz-24; + padding-inline-start: var(--sp-s); + border-radius: $br-6; + background-color: var(--color-background-tertiary); +} + +.multi-input-chip-text { + @include t.use-typography("body-small"); + + color: var(--color-foreground-primary); +} + +.multi-input-chip-icon { + inline-size: $sz-24; + block-size: $sz-24; +} diff --git a/frontend/src/app/main/ui/onboarding/questions.cljs b/frontend/src/app/main/ui/onboarding/questions.cljs index 64fff7896e..f281503bc1 100644 --- a/frontend/src/app/main/ui/onboarding/questions.cljs +++ b/frontend/src/app/main/ui/onboarding/questions.cljs @@ -20,8 +20,7 @@ [cuerdas.core :as str] [rumext.v2 :as mf])) -(mf/defc step-container - {::mf/props :obj} +(mf/defc step-container* [{:keys [form step on-next on-prev children class label]}] (let [on-next* @@ -69,8 +68,7 @@ (and (= role "other") (not (str/blank? role-other)))))]]) -(mf/defc step-1 - {::mf/props :obj} +(mf/defc step-1* [{:keys [on-next form show-step-3]}] (let [use-options (mf/with-memo [] @@ -89,24 +87,25 @@ {:label (tr "labels.product-management") :value "manager" :key "manager"}]) (conj {:label (tr "labels.other-short") :value "other"}))) - current-role (dm/get-in @form [:data :role])] + [:> step-container* {:form form + :step 1 + :label "questions:about-you" + :on-next on-next + :class (stl/css :step)} - [:& step-container {:form form - :step 1 - :label "questions:about-you" - :on-next on-next - :class (stl/css :step-1)} - - [:div {:class (stl/css :paginator)} (str/ffmt "1/%" (if @show-step-3 4 3))] + [:div {:class (stl/css :paginator)} + (str/ffmt "1/%" (if @show-step-3 4 3))] [:img {:class (stl/css :header-image) - :src "images/form/use-for-1.png" + :src "images/form/slide-1-help-us-know-you.svg" :alt (tr "onboarding.questions.lets-get-started")}] + [:h1 {:class (stl/css :modal-title)} (tr "onboarding.questions.step1.title")] + [:p {:class (stl/css :modal-text)} (tr "onboarding.questions.step1.subtitle")] @@ -116,17 +115,18 @@ [:& fm/radio-buttons {:options use-options :name :expected-use - :class (stl/css :radio-btns)}] + :class (stl/css :radio)}] + + [:h3 {:class (stl/css :modal-subtitle)} + (tr "onboarding.questions.step3.question1")] - [:h3 {:class (stl/css :modal-subtitle)} (tr "onboarding.questions.step3.question1")] [:& fm/select {:options role-options - :select-class (stl/css :select-class) + :select-class (stl/css :select) :default "" :name :role}] (when (= current-role "other") [:& fm/input {:name :role-other - :class (stl/css :input-spacing) :placeholder (tr "labels.other") :show-error false :label ""}])]])) @@ -147,21 +147,20 @@ (and (= experience "other") (not (str/blank? experience-other))))))]]) -(mf/defc step-2 - {::mf/props :obj} +(mf/defc step-2* [{:keys [on-next on-prev form show-step-3]}] (let [design-tool-options (mf/with-memo [] (-> (shuffle [{:label (tr "labels.figma") :img-width "48px" :img-height "60px" - :value "figma" :image "images/form/figma.png"} + :value "figma" :image "images/form/slide-2-figma.png"} {:label (tr "labels.sketch") :img-width "48px" :img-height "60px" - :value "sketch" :image "images/form/sketch.png"} + :value "sketch" :image "images/form/slide-2-sketch.png"} {:label (tr "labels.adobe-xd") :img-width "48px" :img-height "60px" - :value "adobe-xd" :image "images/form/adobe-xd.png"} + :value "adobe-xd" :image "images/form/slide-2-adobe-xd.png"} {:label (tr "labels.canva") :img-width "48px" :img-height "60px" - :value "canva" :image "images/form/canva.png"} + :value "canva" :image "images/form/slide-2-canva.png"} {:label (tr "labels.invision") :img-width "48px" :img-height "60px" - :value "invision" :image "images/form/invision.png"}]) + :value "invision" :image "images/form/slide-2-invision.png"}]) (conj {:label (tr "labels.other-short") :value "other" :icon deprecated-icon/curve}))) current-experience @@ -175,43 +174,41 @@ (swap! form d/dissoc-in [:data :experience-design-tool-other]) (swap! form d/dissoc-in [:errors :experience-design-tool-other]))))] - [:& step-container {:form form - :step 2 - :label "questions:experience-design-tool" - :on-next on-next - :on-prev on-prev - :class (stl/css :step-2)} - - [:div {:class (stl/css :paginator)} (str/ffmt "2/%" (if @show-step-3 4 3))] + [:> step-container* {:form form + :step 2 + :label "questions:experience-design-tool" + :on-next on-next + :on-prev on-prev + :class (stl/css :step)} + [:div {:class (stl/css :paginator)} + (str/ffmt "2/%" (if @show-step-3 4 3))] [:h1 {:class (stl/css :modal-title)} (tr "onboarding.questions.step2.title")] + [:div {:class (stl/css :radio-wrapper)} [:& fm/image-radio-buttons {:options design-tool-options :img-width "48px" :img-height "60px" :name :experience-design-tool :image true - :class (stl/css :image-radio) + :class (stl/css :radio-image) :on-change on-design-tool-change}] (when (= current-experience "other") [:& fm/input {:name :experience-design-tool-other - :class (stl/css :input-spacing) :placeholder (tr "labels.other") :show-error false :label ""}])]])) - (def ^:private schema:questions-form-3 [:and [:map {:title "QuestionsFormStep3"} [:team-size [:enum "1" "2-100" "101-500" "501-1000" "1001-5000" "5001+"]]]]) -(mf/defc step-3 - {::mf/props :obj} +(mf/defc step-3* [{:keys [on-next on-prev form show-step-3]}] (let [team-size-options (mf/with-memo [] @@ -231,14 +228,15 @@ {:label (tr "onboarding.questions.team-size.more-than-5001") :value "5001+" :key "5001+"}])] - [:& step-container {:form form - :step 3 - :label "questions:about-your-job" - :on-next on-next - :on-prev on-prev - :class (stl/css :step-3)} + [:> step-container* {:form form + :step 3 + :label "questions:about-your-job" + :on-next on-next + :on-prev on-prev + :class (stl/css :step)} - [:div {:class (stl/css :paginator)} (str/ffmt "3/%" (if @show-step-3 4 3))] + [:div {:class (stl/css :paginator)} + (str/ffmt "3/%" (if @show-step-3 4 3))] [:h1 {:class (stl/css :modal-title)} (tr "onboarding.questions.step3.title")] @@ -246,7 +244,7 @@ [:div {:class (stl/css :modal-question)} [:& fm/select {:options team-size-options :default "" - :select-class (stl/css :select-class) + :select-class (stl/css :select) :name :team-size}]]])) (def ^:private schema:questions-form-4 @@ -262,21 +260,20 @@ (and (= start-with "other") (not (str/blank? start-with-other)))))]]) -(mf/defc step-4 - {::mf/props :obj} +(mf/defc step-4* [{:keys [on-next on-prev form show-step-3]}] (let [start-options (mf/with-memo [] (-> (shuffle [{:label (tr "onboarding.questions.start-with.ui") - :value "ui" :image "images/form/Design.png"} + :value "ui" :image "images/form/slide-3-design-app-ui-ux.svg"} {:label (tr "onboarding.questions.start-with.wireframing") - :value "wireframing" :image "images/form/templates.png"} + :value "wireframing" :image "images/form/slide-3-wireframing.svg"} {:label (tr "onboarding.questions.start-with.prototyping") - :value "prototyping" :image "images/form/Prototype.png"} + :value "prototyping" :image "images/form/slide-3-prototyping.svg"} {:label (tr "onboarding.questions.start-with.ds") - :value "ds" :image "images/form/components.png"} + :value "ds" :image "images/form/slide-3-design-systems.svg"} {:label (tr "onboarding.questions.start-with.code") - :value "code" :image "images/form/design-and-dev.png"}]) + :value "code" :image "images/form/slide-3-code-from-design.svg"}]) (conj {:label (tr "labels.other-short") :value "other" :icon deprecated-icon/curve}))) current-start (dm/get-in @form [:data :start-with]) @@ -284,37 +281,37 @@ on-start-change (mf/use-fn (mf/deps current-start) - (fn [_ _] + (fn [] (when (not= current-start "other") (swap! form d/dissoc-in [:data :start-with-other]) (swap! form d/dissoc-in [:errors :start-with-other]))))] - [:& step-container {:form form - :step 4 - :label "questions:how-start" - :on-next on-next - :on-prev on-prev - :class (stl/css :step-4)} + [:> step-container* {:form form + :step 4 + :label "questions:how-start" + :on-next on-next + :on-prev on-prev + :class (stl/css :step)} - [:div {:class (stl/css :paginator)} (str/ffmt "%/%" (if @show-step-3 4 3) (if @show-step-3 4 3))] + [:div {:class (stl/css :paginator)} + (str/ffmt "%/%" (if @show-step-3 4 3) (if @show-step-3 4 3))] + + [:h1 {:class (stl/css :modal-title)} + (tr "onboarding.questions.step4.title")] - [:h1 {:class (stl/css :modal-title)} (tr "onboarding.questions.step4.title")] [:div {:class (stl/css :radio-wrapper)} [:& fm/image-radio-buttons {:options start-options - :img-width "159px" - :img-height "120px" + :img-width "100px" + :img-height "110px" :name :start-with :on-change on-start-change}] (when (= current-start "other") [:& fm/input {:name :start-with-other - :class (stl/css :input-spacing) :label "" :show-error false :placeholder (tr "labels.other")}])]])) - - (mf/defc questions-modal [] (let [container (mf/use-ref) @@ -369,10 +366,10 @@ :ref container} (case @step - 1 [:& step-1 {:on-next on-next :on-prev on-prev :form step-1-form :show-step-3 show-step-3}] - 2 [:& step-2 {:on-next on-next :on-prev on-prev :form step-2-form :show-step-3 show-step-3}] + 1 [:> step-1* {:on-next on-next :on-prev on-prev :form step-1-form :show-step-3 show-step-3}] + 2 [:> step-2* {:on-next on-next :on-prev on-prev :form step-2-form :show-step-3 show-step-3}] 3 (if @show-step-3 - [:& step-3 {:on-next on-next :on-prev on-prev :form step-3-form :show-step-3 show-step-3}] - [:& step-4 {:on-next on-submit :on-prev on-prev :form step-4-form :show-step-3 show-step-3}]) + [:> step-3* {:on-next on-next :on-prev on-prev :form step-3-form :show-step-3 show-step-3}] + [:> step-4* {:on-next on-submit :on-prev on-prev :form step-4-form :show-step-3 show-step-3}]) (when @show-step-3 - 4 [:& step-4 {:on-next on-submit :on-prev on-prev :form step-4-form :show-step-3 show-step-3}]))]])) + 4 [:> step-4* {:on-next on-submit :on-prev on-prev :form step-4-form :show-step-3 show-step-3}]))]])) diff --git a/frontend/src/app/main/ui/onboarding/questions.scss b/frontend/src/app/main/ui/onboarding/questions.scss index 4438dcc1fb..d9363415f7 100644 --- a/frontend/src/app/main/ui/onboarding/questions.scss +++ b/frontend/src/app/main/ui/onboarding/questions.scss @@ -5,37 +5,15 @@ // Copyright (c) KALEIDOS INC Sucursal en España SL @use "refactor/common-refactor.scss" as deprecated; +@use "ds/typography.scss" as t; +@use "ds/_borders.scss" as *; +@use "ds/_sizes.scss" as *; +@use "ds/_utils.scss" as *; .modal-overlay { @extend %modal-overlay-base; } -.modal-container { - max-width: deprecated.$s-960; - max-height: fit-content; - width: fit-content; - padding-inline: deprecated.$s-100; - padding-block: deprecated.$s-40 deprecated.$s-72; - border-radius: deprecated.$br-8; - border: deprecated.$s-2 solid var(--modal-border-color); - background-color: var(--modal-background-color); -} - -.form-wrapper { - display: grid; - grid-template-columns: 1fr; - gap: deprecated.$s-24; -} - -// STEP CONTAINER -.paginator { - @include deprecated.small-title-typography; - - height: deprecated.$s-20; - text-align: right; - color: var(--modal-text-foreground-color); -} - .action-buttons { @extend %modal-action-btns; } @@ -48,29 +26,51 @@ @extend %modal-cancel-btn; } -.radio-btns label, -.select-class span { - @include deprecated.body-medium-typography; +.modal-container { + max-width: $sz-964; + max-height: fit-content; + inline-size: fit-content; + padding-inline: $sz-96; + padding-block: $sz-40 $sz-64; + border-radius: $br-8; + border: $b-2 solid var(--modal-border-color); + background-color: var(--modal-background-color); } -// STEP 1 +.form-wrapper { + display: grid; + grid-template-columns: 1fr; + gap: var(--sp-xxl); +} + +.paginator { + @include t.use-typography("title-small"); + + text-align: right; + color: var(--modal-text-foreground-color); +} + +.radio label, +.select span { + @include t.use-typography("body-medium"); +} .header-image { - height: deprecated.$s-60; - width: auto; + block-size: $sz-120; + inline-size: auto; margin-inline-start: auto; } .modal-title { - @include deprecated.big-title-typography; + @include t.use-typography("title-large"); color: var(--modal-title-foreground-color); - min-height: deprecated.$s-32; + min-block-size: $sz-32; margin-block: auto; } .modal-subtitle { - @include deprecated.body-large-typography; + @include t.use-typography("body-large"); color: var(--modal-title-foreground-color); margin: 0; @@ -78,71 +78,35 @@ } .modal-text { - @include deprecated.body-large-typography; + @include t.use-typography("body-large"); color: var(--modal-text-foreground-color); margin: 0; } -// STEP-2 -.step-1, -.step-2, -.step-3, -.step-5 { - max-width: deprecated.$s-540; - width: deprecated.$s-540; -} - -.step-2 { - grid-template-rows: deprecated.$s-20 auto auto deprecated.$s-32; +.step { + max-inline-size: $sz-520; + inline-size: $sz-520; } .modal-question { display: grid; grid-template-columns: 1fr; - grid-template-rows: deprecated.$s-16 deprecated.$s-32; - gap: deprecated.$s-16; - height: fit-content; -} - -.question-centered { - width: deprecated.$s-424; - grid-template-rows: auto deprecated.$s-32; - margin: 0 auto; + grid-template-rows: $sz-16 $sz-32; + gap: var(--sp-l); + block-size: fit-content; } .radio-wrapper { display: grid; grid-template-columns: 1fr; - gap: deprecated.$s-16; + gap: var(--sp-l); } -// STEP-3 -.step-3 { - grid-template-rows: deprecated.$s-20 auto auto deprecated.$s-32; -} - -.image-radio { +.radio-image { display: grid; grid-template-rows: 1fr 1fr; - grid-template-columns: deprecated.$s-92 deprecated.$s-92 deprecated.$s-92; - gap: deprecated.$s-16 deprecated.$s-24; + grid-template-columns: $sz-96 $sz-96 $sz-96; + gap: var(--sp-l) var(--sp-xxl); justify-content: center; } - -.input-spacing { - height: deprecated.$s-32; - width: 100%; - margin-block-end: deprecated.$s-8; -} - -.input-spacing input { - @include deprecated.body-medium-typography; -} - -// STEP-4 - -.step-4 { - grid-template-rows: deprecated.$s-20 auto auto deprecated.$s-32; - row-gap: deprecated.$s-16; -} diff --git a/frontend/src/app/main/ui/onboarding/team_choice.cljs b/frontend/src/app/main/ui/onboarding/team_choice.cljs index af457b2dd3..0b15964681 100644 --- a/frontend/src/app/main/ui/onboarding/team_choice.cljs +++ b/frontend/src/app/main/ui/onboarding/team_choice.cljs @@ -14,47 +14,61 @@ [app.main.data.profile :as du] [app.main.data.team :as dtm] [app.main.store :as st] - [app.main.ui.components.forms :as fm] - [app.main.ui.icons :as deprecated-icon] - [app.main.ui.notifications.context-notification :refer [context-notification]] + [app.main.ui.components.link :refer [link*]] + [app.main.ui.ds.foundations.assets.icon :refer [icon*] :as i] + [app.main.ui.ds.foundations.typography :as t] + [app.main.ui.ds.foundations.typography.heading :refer [heading*]] + [app.main.ui.ds.foundations.typography.text :refer [text*]] + [app.main.ui.ds.notifications.context-notification :refer [context-notification*]] + [app.main.ui.forms :as fc] + [app.util.forms :as fm] [app.util.i18n :as i18n :refer [tr]] [rumext.v2 :as mf])) -(mf/defc left-sidebar* +(mf/defc team-info-feature* + {::mf/private true} + [{:keys [icon-id text]}] + [:li {:class (stl/css :modal-info-item)} + [:div {:class (stl/css :modal-info-icon)} + [:> icon* {:icon-id icon-id :size "m"}]] + [:> text* {:as "div" + :typography t/body-medium + :class (stl/css :color-light)} + text]]) + +(mf/defc team-info* {::mf/private true} [] - [:div {:class (stl/css :modal-left)} - [:h2 {:class (stl/css :modal-subtitle)} + [:div {:class (stl/css :modal-info)} + [:img {:src "images/form/slide-final-team.svg"}] + + [:> heading* {:level 2 + :typography t/title-medium + :class (stl/css :color-light)} (tr "onboarding.team-modal.team-definition")] - [:p {:class (stl/css :modal-text)} + + [:> text* {:as "div" + :typography t/body-medium + :class (stl/css :color-dimmed :margin-bottom)} (tr "onboarding.team-modal.create-team-desc")] - [:ul {:class (stl/css :team-features)} - [:li {:class (stl/css :feature)} - [:span {:class (stl/css :icon)} deprecated-icon/document] - [:p {:class (stl/css :modal-desc)} - (tr "onboarding.team-modal.create-team-feature-1")]] - [:li {:class (stl/css :feature)} - [:span {:class (stl/css :icon)} deprecated-icon/move] - [:p {:class (stl/css :modal-desc)} - (tr "onboarding.team-modal.create-team-feature-2")]] - [:li {:class (stl/css :feature)} - [:span {:class (stl/css :icon)} deprecated-icon/tree] - [:p {:class (stl/css :modal-desc)} - (tr "onboarding.team-modal.create-team-feature-3")]] - [:li {:class (stl/css :feature)} - [:span {:class (stl/css :icon)} deprecated-icon/user] - [:p {:class (stl/css :modal-desc)} - (tr "onboarding.team-modal.create-team-feature-4")]] - [:li {:class (stl/css :feature)} - [:span {:class (stl/css :icon)} deprecated-icon/tick] - [:p {:class (stl/css :modal-desc)} - (tr "onboarding.team-modal.create-team-feature-5")]]]]) + + [:ul {:class (stl/css :modal-info-features)} + [:> team-info-feature* {:icon-id i/document + :text (tr "onboarding.team-modal.create-team-feature-1")}] + [:> team-info-feature* {:icon-id i/move + :text (tr "onboarding.team-modal.create-team-feature-2")}] + [:> team-info-feature* {:icon-id i/tree + :text (tr "onboarding.team-modal.create-team-feature-3")}] + [:> team-info-feature* {:icon-id i/user + :text (tr "onboarding.team-modal.create-team-feature-4")}] + [:> team-info-feature* {:icon-id i/tick + :text (tr "onboarding.team-modal.create-team-feature-5")}]]]) (defn- get-available-roles [] - [{:value "viewer" :label (tr "labels.viewer")} - {:value "editor" :label (tr "labels.editor")} - {:value "admin" :label (tr "labels.admin")}]) + [{:id "viewer" :value "viewer" :label (tr "labels.viewer")} + {:id "editor" :value "editor" :label (tr "labels.editor")} + {:id "admin" :value "admin" :label (tr "labels.admin")}]) (def ^:private schema:team-form [:map {:title "TeamForm"} @@ -68,8 +82,8 @@ (let [initial (mf/with-memo [] {:role "editor"}) - form (fm/use-form :schema schema:team-form - :initial initial) + form (fm/use-form :schema schema:team-form + :initial initial) roles (mf/use-memo get-available-roles) @@ -109,7 +123,7 @@ :else (swap! error* (tr "errors.generic")))))) - on-invite-later + on-create-without-invitations (mf/use-fn (fn [{:keys [name]}] (let [mdata {:on-success on-success @@ -117,126 +131,123 @@ params {:name name}] (st/emit! (-> (dtm/create-team (with-meta params mdata)) (with-meta {::ev/origin :onboarding-without-invitations})) - (ev/event - {::ev/name "onboarding-step" - :label "team:create-team-and-invite-later" - :team-name name - :step 8}) - (ev/event - {::ev/name "onboarding-finish"}))))) + (ev/event {::ev/name "onboarding-step" + :label "team:create-team-and-invite-later" + :team-name name + :step 8}) + (ev/event {::ev/name "onboarding-finish"}))))) - on-invite-now + on-create-with-invitations (mf/use-fn (fn [{:keys [name emails] :as params}] (let [mdata {:on-success on-success :on-error on-error}] - (st/emit! (-> (dtm/create-team-with-invitations (with-meta params mdata)) (with-meta {::ev/origin :onboarding-with-invitations})) - (ev/event - {::ev/name "onboarding-step" - :label "team:create-team-and-invite" - :invites (count emails) - :team-name name - :role (:role params) - :step 8}) - (ev/event - {::ev/name "onboarding-finish"}))))) + (ev/event {::ev/name "onboarding-step" + :label "team:create-team-and-invite" + :invites (count emails) + :team-name name + :role (:role params) + :step 8}) + (ev/event {::ev/name "onboarding-finish"}))))) - on-submit* + on-submit (mf/use-fn (fn [form] (let [params (:clean-data @form) emails (:emails params)] (if (> (count emails) 0) - (on-invite-now params) - (on-invite-later params))))) + (on-create-with-invitations params) + (on-create-without-invitations params))))) on-skip (mf/use-fn (fn [] (st/emit! (du/update-profile-props {:onboarding-viewed true}) - (ev/event - {::ev/name "onboarding-step" - :label "team:skip-team-creation" - :step 7}) - (ev/event - {::ev/name "onboarding-finish"}))))] - [:* - [:div {:class (stl/css :modal-right)} - [:div {:class (stl/css :first-block)} - [:& fm/form {:form form - :class (stl/css :modal-form) - :on-submit on-submit*} - [:h2 {:class (stl/css :modal-subtitle)} - (tr "onboarding.team-modal.create-team")] - [:p {:class (stl/css :modal-text)} - (tr "onboarding.choice.team-up.create-team-desc")] + (ev/event {::ev/name "onboarding-step" + :label "team:skip-team-creation" + :step 7}) + (ev/event {::ev/name "onboarding-finish"}))))] + [:div {:class (stl/css :modal-team)} + [:> fc/form* {:form form + :class (stl/css :modal-team-form) + :on-submit on-submit} - [:& fm/input {:type "text" - :class (stl/css :team-name-input) - :name :name - :auto-focus? true - :placeholder "Team name" - :label (tr "onboarding.choice.team-up.create-team-placeholder")}] + [:div {:class (stl/css :modal-team-block)} + [:> heading* {:level 2 + :typography t/title-medium + :class (stl/css :color-light)} + (tr "onboarding.team-modal.create-team")] - [:h2 {:class (stl/css :modal-subtitle :invite-subtitle)} (tr "onboarding.choice.team-up.invite-members")] - [:p {:class (stl/css :modal-text)} (tr "onboarding.choice.team-up.invite-members-info")] + [:> fc/form-input* {:type "text" + :name :name + :auto-focus true + :auto-complete "off" + :placeholder (tr "onboarding.choice.team-up.create-team-placeholder")}] - (when-let [content (deref error*)] - [:& context-notification {:content content :level :error}]) + [:> text* {:as "div" + :typography t/body-small + :class (stl/css :color-dimmed)} + (tr "onboarding.choice.team-up.create-team-desc")]] - [:div {:class (stl/css :role-select)} - [:p {:class (stl/css :role-title)} (tr "onboarding.choice.team-up.roles")] - [:& fm/select {:name :role :options roles}]] + [:div {:class (stl/css :modal-team-block)} + [:> heading* {:level 2 + :typography t/title-medium + :class (stl/css :color-light)} + (tr "onboarding.choice.team-up.invite-members")] - [:div {:class (stl/css :invitation-row)} - [:& fm/multi-input {:type "email" - :name :emails - :trim true - :valid-item-fn sm/parse-email - :caution-item-fn #{} - :label (tr "modals.invite-member.emails")}]] + (when-let [content (deref error*)] + [:> context-notification* {:level :error} + content]) + [:div {:class (stl/css :modal-team-sub-block)} + [:> fc/form-select* {:name :role + :options roles}] + [:> fc/form-multi-input* {:type "email" + :name :emails + :trim true + :valid-item-fn sm/parse-email + :caution-item-fn #{} + :auto-complete "off" + :placeholder (tr "modals.invite-member.emails")}]] + [:> text* {:as "div" + :typography t/body-small + :class (stl/css :color-dimmed)} + (tr "onboarding.choice.team-up.invite-members-info")] - (let [params (:clean-data @form) - emails (:emails params)] - [:* - [:div {:class (stl/css :action-buttons)} + (let [params (:clean-data @form) + emails (:emails params) + num-emails (count emails)] + [:* + [:div {:class (stl/css :flex-align-right)} + [:> fc/form-submit* {:variant "primary"} + (if (> num-emails 0) + (tr "onboarding.choice.team-up.create-team-and-invite") + (tr "onboarding.choice.team-up.create-team-without-invite"))]] - [:> fm/submit-button* - {:class (stl/css :accept-button) - :label (if (> (count emails) 0) - (tr "onboarding.choice.team-up.create-team-and-invite") - (tr "onboarding.choice.team-up.create-team-without-invite"))}]] + (when (= num-emails 0) + [:> text* {:as "div" + :typography t/body-small + :class (stl/css :color-dimmed :text-align-right)} + "(" (tr "onboarding.choice.team-up.create-team-and-send-invites-description") ")"])])]] - (when (= (count emails) 0) - [:> :div {:class (stl/css :modal-hint)} - "(" (tr "onboarding.choice.team-up.create-team-and-send-invites-description") ")"])])]] - - [:div {:class (stl/css :second-block)} - [:h2 {:class (stl/css :modal-subtitle)} - (tr "onboarding.choice.team-up.start-without-a-team")] - [:p {:class (stl/css :modal-text)} - (tr "onboarding.choice.team-up.start-without-a-team-description")] - - [:div {:class (stl/css :action-buttons)} - [:button {:class (stl/css :accept-button) - :on-click on-skip} - (tr "onboarding.choice.team-up.continue-without-a-team")]]]]])) + [:div {:class (stl/css :link-wrapper)} + [:> link* {:class (stl/css :link) + :action on-skip} + (tr "onboarding.choice.team-up.continue-without-a-team")]]])) (mf/defc onboarding-team-modal* [{:keys [go-to-team]}] - - [:div {:class (stl/css-case - :modal-overlay true)} - + [:div {:class (stl/css-case :modal-overlay true)} [:div.animated.fade-in {:class (stl/css :modal-container)} - [:h1 {:class (stl/css :modal-title)} + [:> heading* {:level 1 + :typography t/title-large + :class (stl/css :color-light)} (tr "onboarding-v2.welcome.title")] [:div {:class (stl/css :modal-sections)} - [:> left-sidebar*] - [:div {:class (stl/css :separator)}] + [:> team-info*] + [:div {:class (stl/css :modal-separator)} + [:div {:class (stl/css :modal-separator-line)}]] [:> team-form* {:go-to-team go-to-team}]]]]) - diff --git a/frontend/src/app/main/ui/onboarding/team_choice.scss b/frontend/src/app/main/ui/onboarding/team_choice.scss index 5c8c4c78d9..e948531c6f 100644 --- a/frontend/src/app/main/ui/onboarding/team_choice.scss +++ b/frontend/src/app/main/ui/onboarding/team_choice.scss @@ -5,216 +5,140 @@ // Copyright (c) KALEIDOS INC Sucursal en España SL @use "refactor/common-refactor.scss" as deprecated; +@use "ds/typography.scss" as t; +@use "ds/_borders.scss" as *; +@use "ds/_sizes.scss" as *; +@use "ds/_utils.scss" as *; + +.color-light { + color: var(--color-foreground-primary); +} + +.color-dimmed { + color: var(--color-foreground-secondary); +} + +.text-align-right { + text-align: right; +} + +.flex-align-right { + display: flex; + justify-content: flex-end; +} + +.margin-bottom { + margin-bottom: var(--sp-xxl); +} + +.link-wrapper { + display: flex; + justify-content: center; +} + +.link { + @include t.use-typography("body-small"); + + cursor: pointer; + text-decoration: underline; + text-align: center; + text-transform: uppercase; + color: var(--color-foreground-secondary); + + &:hover { + color: var(--color-foreground-primary); + } +} .modal-overlay { @extend %modal-overlay-base; } .modal-container { - position: relative; - width: deprecated.$s-908; - max-height: deprecated.$s-800; - height: 100%; - padding-inline: deprecated.$s-100; - padding-block: deprecated.$s-40 deprecated.$s-40; - border-radius: deprecated.$br-8; - background-color: var(--modal-background-color); - border: deprecated.$s-2 solid var(--modal-border-color); display: flex; flex-direction: column; - gap: deprecated.$s-24; + gap: var(--sp-xxl); + position: relative; + inline-size: px2rem(908); + padding: $sz-64 px2rem(100); + border-radius: $br-8; + background-color: var(--color-background-primary); + border: $b-2 solid var(--color-background-quaternary); } .modal-sections { display: grid; - grid-template-columns: 1fr deprecated.$s-32 1fr; - gap: deprecated.$s-24; - height: 100%; - overflow: hidden; + grid-template-columns: px2rem(310) $sz-32 1fr; + gap: var(--sp-xxl); + block-size: 100%; } -.paginator { - @include deprecated.body-small-typography; - - position: absolute; - top: deprecated.$s-40; - right: deprecated.$s-100; - padding: deprecated.$s-4; - border-radius: deprecated.$br-6; - color: var(--color-foreground-secondary); +.modal-info { + display: flex; + flex-direction: column; + gap: var(--sp-xl); + border: $b-1 solid var(--color-foreground-secondary); + padding: var(--sp-m); + border-radius: $br-12; + background-color: var(--color-background-quaternary); } -// MODAL LEFT -.modal-left { +.modal-info-features { + display: flex; + flex-direction: column; + gap: var(--sp-m); +} + +.modal-info-item { + display: flex; + align-items: center; + gap: var(--sp-l); +} + +.modal-info-icon { + display: flex; + align-items: center; + justify-content: center; + inline-size: $sz-32; + block-size: $sz-32; + border-radius: $br-circle; + border: $b-1 solid var(--color-accent-primary); + color: var(--color-accent-primary); +} + +.modal-separator { + display: flex; + justify-content: center; +} + +.modal-separator-line { + inline-size: px2rem(8); + block-size: 100%; + border-radius: $br-8; + opacity: 0.5; + background-color: var(--color-background-quaternary); +} + +.modal-team { + display: flex; + flex-direction: column; + gap: var(--sp-xl); +} + +.modal-team-form { display: grid; grid-template-columns: 1fr; - grid-template-rows: deprecated.$s-32 auto auto 1fr; - gap: deprecated.$s-16; - overflow: auto; + gap: var(--sp-xxl); } -.modal-title { - @include deprecated.big-title-typography; - - color: var(--modal-title-foreground-color); +.modal-team-block { + display: flex; + flex-direction: column; + gap: var(--sp-m); } -.modal-subtitle { - @include deprecated.med-title-typography; - - color: var(--modal-title-foreground-color); -} - -.invite-subtitle { - padding-top: deprecated.$s-16; -} - -.modal-text { - @include deprecated.body-large-typography; - - color: var(--modal-text-foreground-color); - margin: 0; -} - -.modal-desc { - @include deprecated.small-title-typography; - - margin: 0; - color: var(--modal-title-foreground-color); -} - -.team-features { - @include deprecated.flex-column; - - gap: deprecated.$s-16; - margin: 0; -} - -.feature { - @include deprecated.flex-row; - - gap: deprecated.$s-16; -} - -.icon { - @include deprecated.flex-center; - - height: deprecated.$s-32; - width: deprecated.$s-32; - border-radius: deprecated.$br-circle; - border: deprecated.$s-1 solid var(--color-accent-primary); - - svg { - @extend %button-icon; - - stroke: var(--color-accent-primary); - } -} - -.action-buttons { - @extend %modal-action-btns; - - justify-content: flex-end; -} - -.accept-button { - @extend %modal-accept-btn; -} - -.back-button { - @extend %modal-cancel-btn; -} - -// SEPARATOR -.separator { - width: deprecated.$s-8; - height: 100%; - border-radius: deprecated.$br-8; - opacity: 0.42; - background-color: var(--modal-separator-background-color); -} - -// MODAL RIGHT TEAM -.modal-right { - display: grid; - grid-template-columns: 1fr; - grid-template-rows: 1fr auto; - gap: deprecated.$s-24; - overflow: hidden; -} - -.first-block { - overflow: auto; - flex-grow: 1; -} - -.first-block, -.second-block { - @include deprecated.flex-column; - - gap: deprecated.$s-16; -} - -.modal-form { - display: grid; - grid-template-columns: 1fr; - gap: deprecated.$s-16; -} - -.team-name-input { - @extend %input-element-label; - - label { - @include deprecated.flex-column; - @include deprecated.body-small-typography; - - align-items: flex-start; - width: 100%; - border: none; - background-color: transparent; - height: 100%; - - input { - @include deprecated.body-small-typography; - - margin-top: deprecated.$s-8; - } - } -} - -// MODAL RIGHT INVITATIONS - -.modal-right-invitations { - display: grid; - grid-template-columns: 1fr; - grid-template-rows: auto auto 1fr; - gap: deprecated.$s-16; - max-height: deprecated.$s-512; -} - -.modal-form-invitations { - display: grid; - grid-template-columns: 1fr; - grid-template-rows: auto 1fr auto auto; - margin-block-end: deprecated.$s-72; - gap: deprecated.$s-8; -} - -.role-title { - @include deprecated.uppercase-title-typography; - - margin-block-end: deprecated.$s-8; - color: var(--modal-title-foreground-color); -} - -.invitation-row { - margin: 0; - color: var(--modal-title-foreground-color); -} - -.modal-hint { - @include deprecated.body-small-typography; - - color: var(--modal-text-foreground-color); - text-align: right; +.modal-team-sub-block { + display: flex; + flex-direction: column; + gap: var(--sp-s); } diff --git a/frontend/translations/en.po b/frontend/translations/en.po index 12aa2313b1..1faf2b134d 100644 --- a/frontend/translations/en.po +++ b/frontend/translations/en.po @@ -19,6 +19,9 @@ msgstr "Already have an account?" msgid "auth.check-mail" msgstr "Check your email" +msgid "auth.check-email" +msgstr "Check your email!" + #: src/app/main/ui/auth/register.cljs:277 #, unused msgid "auth.check-your-email" @@ -193,6 +196,9 @@ msgstr "" msgid "auth.verification-email-sent" msgstr "We've sent a verification email to" +msgid "auth.verification-sent-email" +msgstr "We've sent a verification email to:" + #: src/app/main/ui/auth/login.cljs:178, src/app/main/ui/auth/recovery_request.cljs:77, src/app/main/ui/auth/register.cljs:168 msgid "auth.work-email" msgstr "Work email" @@ -4746,7 +4752,7 @@ msgstr "Invite members" #: src/app/main/ui/onboarding/team_choice.cljs:187 msgid "onboarding.choice.team-up.invite-members-info" msgstr "" -"Remember to include everyone. Developers, designers, managers... diversity " +"Remember to include everyone. Developers, designers, managers... Diversity " "adds up :)" #: src/app/main/ui/dashboard/team.cljs:258, src/app/main/ui/onboarding/team_choice.cljs:193 diff --git a/frontend/translations/es.po b/frontend/translations/es.po index a2d4b750a7..97774a7169 100644 --- a/frontend/translations/es.po +++ b/frontend/translations/es.po @@ -19,6 +19,9 @@ msgstr "¿Tienes ya una cuenta?" msgid "auth.check-mail" msgstr "Comprueba tu correo" +msgid "auth.check-email" +msgstr "¡Comprueba tu correo!" + #: src/app/main/ui/auth/register.cljs:277 #, unused msgid "auth.check-your-email" @@ -198,6 +201,9 @@ msgstr "" msgid "auth.verification-email-sent" msgstr "Hemos enviado un email de verificación a" +msgid "auth.verification-sent-email" +msgstr "Hemos enviado un email de verificación a:" + #: src/app/main/ui/auth/login.cljs:178, src/app/main/ui/auth/recovery_request.cljs:77, src/app/main/ui/auth/register.cljs:168 msgid "auth.work-email" msgstr "Correo electrónico"