Update onboarding modals

This commit is contained in:
Eva Marco 2024-05-30 10:06:25 +02:00 committed by Andrey Antukh
parent 55ce9bef49
commit fda6deaa4f
85 changed files with 938 additions and 1482 deletions

View file

@ -491,6 +491,7 @@
ptk/WatchEvent
(watch [_ _ _]
(let [props {:onboarding-questions-answered true
:onboarding-viewed true
:onboarding-questions onboarding-questions}]
(->> (rp/cmd! :update-profile-props {:props props})
(rx/map (constantly (fetch-profile))))))))

View file

@ -15,7 +15,9 @@
[app.main.ui.frame-preview :as frame-preview]
[app.main.ui.icons :as i]
[app.main.ui.messages :as msgs]
[app.main.ui.onboarding :refer [onboarding-modal]]
[app.main.ui.onboarding.newsletter :refer [onboarding-newsletter]]
[app.main.ui.onboarding.questions :refer [questions-modal]]
[app.main.ui.onboarding.team-choice :refer [onboarding-team-modal]]
[app.main.ui.releases :refer [release-notes-modal]]
[app.main.ui.static :as static]
[app.util.dom :as dom]
@ -96,19 +98,37 @@
#_[:& app.main.ui.onboarding/onboarding-modal]
#_[:& app.main.ui.onboarding.team-choice/onboarding-team-modal]
(when-let [props (get profile :props)]
(cond
(and (not (:onboarding-viewed props))
(contains? cf/flags :onboarding))
[:& onboarding-modal {}]
(let [show-question-modal? (and (not (:onboarding-viewed props))
(contains? cf/flags :onboarding)
(not (:onboarding-questions-answered props))
(contains? cf/flags :onboarding-questions))
(and (contains? cf/flags :onboarding)
(:onboarding-viewed props)
(not= (:release-notes-viewed props) (:main cf/version))
(not= "0.0" (:main cf/version)))
[:& release-notes-modal {:version (:main cf/version)}]))
show-newsletter-modal? (and (not (:onboarding-viewed props))
(contains? cf/flags :onboarding)
(contains? cf/flags :onboarding-newsletter))
show-team-modal? (and (not (:onboarding-viewed props))
(contains? cf/flags :onboarding)
(contains? cf/flags :onboarding-team))
show-release-modal? (and (contains? cf/flags :onboarding)
(:onboarding-viewed props)
(not= (:release-notes-viewed props) (:main cf/version))
(not= "0.0" (:main cf/version)))]
(cond
show-question-modal?
[:& questions-modal]
show-newsletter-modal?
[:& onboarding-newsletter]
show-team-modal?
[:& onboarding-team-modal]
show-release-modal?
[:& release-notes-modal {:version (:main cf/version)}])))
[:& dashboard-page {:route route :profile profile}]]
:viewer
(let [{:keys [query-params path-params]} route
{:keys [index share-id section page-id interactions-mode frame-id]

View file

@ -44,6 +44,9 @@
{::mf/props :obj}
[{:keys [route]}]
(let [section (dm/get-in route [:data :name])
show-login-icon (and
(not= section :auth-register-validate)
(not= section :auth-register-success))
params (:query-params route)
error (:error params)]
@ -55,8 +58,9 @@
(st/emit! (du/show-redirect-error error))))
[:main {:class (stl/css :auth-section)}
[:h1 {:class (stl/css :logo-container)}
[:a {:href "#/" :title "Penpot" :class (stl/css :logo-btn)} i/logo]]
(when show-login-icon
[:h1 {:class (stl/css :logo-container)}
[:a {:href "#/" :title "Penpot" :class (stl/css :logo-btn)} i/logo]])
[:div {:class (stl/css :login-illustration)}
i/login-illustration]

View file

@ -31,6 +31,7 @@
display: flex;
justify-content: flex-start;
width: $s-120;
height: $s-96;
margin-block-end: $s-52;
}

View file

@ -10,14 +10,22 @@
width: 100%;
padding-block-end: 0;
display: grid;
gap: $s-24;
gap: $s-12;
form {
display: flex;
flex-direction: column;
gap: $s-12;
margin-top: $s-12;
}
}
.auth-title-wrapper {
width: 100%;
padding-block-end: 0;
display: grid;
gap: $s-8;
}
.separator {
border-color: var(--modal-separator-backogrund-color);
margin: 0;

View file

@ -169,7 +169,7 @@
[:& fm/input
{:name :email
:type "email"
:label (tr "auth.email")
:label (tr "auth.work-email")
:class (stl/css :form-field)}]]
[:div {:class (stl/css :fields-row)}

View file

@ -80,7 +80,7 @@
:form form}
[:div {:class (stl/css :fields-row)}
[:& fm/input {:name :email
:label (tr "auth.email")
:label (tr "auth.work-email")
:type "text"
:class (stl/css :form-field)}]]

View file

@ -104,7 +104,7 @@
[:div {:class (stl/css :fields-row)}
[:& fm/input {:type "text"
:name :email
:label (tr "auth.email")
:label (tr "auth.work-email")
:data-test "email-input"
:show-success? true
:class (stl/css :form-field)}]]
@ -134,11 +134,11 @@
(mf/defc register-page
{::mf/props :obj}
[{:keys [params]}]
[:div {:class (stl/css :auth-form-wrapper)}
[:div {:class (stl/css :auth-form-wrapper :register-form)}
[:h1 {:class (stl/css :auth-title)
:data-test "registration-title"} (tr "auth.register-title")]
[:p {:class (stl/css :auth-tagline)}
(tr "auth.login-tagline")]
(tr "auth.register-tagline")]
(when (contains? cf/flags :demo-warning)
[:& login/demo-warning])
@ -229,11 +229,11 @@
(mf/html
[:& tr-html
{:tag-name "div"
:label "auth.terms-privacy-agreement-md"
:label "auth.terms-and-privacy-agreement"
:params [cf/terms-of-service-uri cf/privacy-policy-uri]}])]
[:div {:class (stl/css :fields-row :input-visible :accept-terms-and-privacy-wrapper)}
[:& fm/input {:name :accept-terms-and-privacy
:class "check-primary"
:class (stl/css :checkbox-terms-and-privacy)
:type "checkbox"
:default-checked false
:label terms-label}]]))
@ -247,11 +247,12 @@
(mf/defc register-validate-page
[{:keys [params]}]
[:div {:class (stl/css :auth-form-wrapper)}
[:h1 {:class (stl/css :auth-title)
:data-test "register-title"} (tr "auth.register-title")]
[:div {:class (stl/css :auth-subtitle)} (tr "auth.register-subtitle")]
[:hr {:class (stl/css :separator)}]
[:h1 {:class (stl/css :logo-container)}
[:a {:href "#/" :title "Penpot" :class (stl/css :logo-btn)} i/logo]]
[:div {:class (stl/css :auth-title-wrapper)}
[:h2 {:class (stl/css :auth-title)
:data-test "register-title"} (tr "auth.register-account-title")]
[:div {:class (stl/css :auth-subtitle)} (tr "auth.register-account-tagline")]]
[:& register-validate-form {:params params}]
@ -264,7 +265,11 @@
(mf/defc register-success-page
[{:keys [params]}]
[:div {:class (stl/css :auth-form-wrapper :register-success)}
[:div {:class (stl/css :notification-icon)} i/icon-verify]
[:div {:class (stl/css :notification-text)} (tr "auth.verification-email-sent")]
[:h1 {:class (stl/css :logo-container)}
[:a {:href "#/" :title "Penpot" :class (stl/css :logo-btn)} i/logo]]
[: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")]]
[:div {:class (stl/css :notification-text-email)} (:email params "")]
[:div {:class (stl/css :notification-text)} (tr "auth.check-your-email")]])

View file

@ -8,15 +8,24 @@
@use "./common.scss";
.accept-terms-and-privacy-wrapper {
margin: $s-16 0;
:global(a) {
color: $df-secondary;
font-weight: $fw700;
}
}
.checkbox-terms-and-privacy {
align-items: flex-start;
}
.register-form {
gap: $s-24;
}
.register-success {
padding-bottom: $s-32;
gap: $s-24;
.auth-title {
@include medTitleTipography;
}
}
.notification-icon {
@ -30,9 +39,30 @@
}
}
.notification-text-email,
.notification-text {
font-size: $fs-16;
color: var(--notification-foreground-color-default);
margin-bottom: $s-16;
@include bodyMediumTypography;
color: var(--title-foreground-color);
}
.notification-text-email {
@include medTitleTipography;
font-size: $fs-20;
color: var(--register-confirmation-color);
margin-inline: $s-36;
}
.logo-btn {
height: $s-40;
svg {
width: $s-120;
height: $s-40;
fill: var(--main-icon-foreground);
}
}
.logo-container {
display: flex;
justify-content: flex-start;
width: $s-120;
margin-block-end: $s-24;
}

View file

@ -236,6 +236,7 @@
.reply-form {
textarea {
@extend .input-element;
@include bodySmallTypography;
line-height: 1.45;
height: 100%;
width: 100%;

View file

@ -117,7 +117,7 @@
[:*
(cond
(some? label)
[:label {:class (stl/css-case :input-with-label (not is-checkbox?)
[:label {:class (stl/css-case :input-with-label-form (not is-checkbox?)
:input-label is-text?
:radio-label is-radio?
:checkbox-label is-checkbox?)
@ -214,7 +214,7 @@
[:span {:class (stl/css :hint)} hint])]))
(mf/defc select
[{:keys [options disabled form default dropdown-class] :as props
[{:keys [options disabled form default dropdown-class select-class] :as props
:or {default ""}}]
(let [input-name (get props :name)
form (or form (mf/use-ctx form-ctx))
@ -230,6 +230,7 @@
{:default-value value
:disabled disabled
:options options
:class select-class
:dropdown-class dropdown-class
:on-change handle-change}]]))
@ -297,6 +298,70 @@
:value value'
:checked checked?}]]))]))
(mf/defc image-radio-buttons
{::mf/wrap-props false}
[props]
(let [form (or (unchecked-get props "form")
(mf/use-ctx form-ctx))
name (unchecked-get props "name")
image (unchecked-get props "image")
img-height (unchecked-get props "img-height")
img-width (unchecked-get props "img-width")
current-value (or (dm/get-in @form [:data name] "")
(unchecked-get props "value"))
on-change (unchecked-get props "on-change")
options (unchecked-get props "options")
trim? (unchecked-get props "trim")
class (unchecked-get props "class")
encode-fn (d/nilv (unchecked-get props "encode-fn") identity)
decode-fn (d/nilv (unchecked-get props "decode-fn") identity)
on-change'
(mf/use-fn
(mf/deps on-change form name)
(fn [event]
(let [value (-> event dom/get-target dom/get-value decode-fn)]
(when (some? form)
(swap! form assoc-in [:touched name] true)
(fm/on-input-change form name value trim?))
(when (fn? on-change)
(on-change name value)))))]
[:div {:class (if image
class
(dm/str class " " (stl/css :custom-radio)))}
(for [{:keys [image icon value label area]} options]
(let [icon? (some? icon)
value' (encode-fn value)
checked? (= value current-value)
key (str/ffmt "%-%" (d/name name) (d/name value'))]
[:label {:for key
:key key
:style {:grid-area area}
:class (stl/css-case :radio-label-image true
:global/checked checked?)}
(cond
icon?
[:span {:class (stl/css :icon-inside)
:style {:height img-height
:width img-width}} icon]
:else
[:span {:style {:background-image (str/ffmt "url(%)" image)
:height img-height
:width img-width}
:class (stl/css :image-inside)}])
[:span {:class (stl/css :image-text)} label]
[:input {:on-change on-change'
:type "radio"
:class (stl/css :radio-input)
:id key
:name name
:value value'
:checked checked?}]]))]))
(mf/defc submit-button*
{::mf/wrap-props false}
[{:keys [on-click children label form class name disabled] :as props}]

View file

@ -38,10 +38,9 @@
}
}
.input-with-label {
.input-with-label-form {
@include flexColumn;
gap: $s-8;
@include bodySmallTypography;
justify-content: flex-start;
align-items: flex-start;
height: 100%;
@ -55,6 +54,7 @@
color: var(--input-foreground-color-active);
margin-top: 0;
width: 100%;
max-width: 100%;
height: 100%;
padding: 0 $s-8;
@ -64,6 +64,7 @@
border-radius: $br-8;
}
}
// Input autofill
input:-webkit-autofill,
input:-webkit-autofill:hover,
@ -169,6 +170,10 @@
border-color: var(--input-checkbox-border-color-hover);
}
}
a {
// Need for terms and conditions links on register checkbox
color: var(--link-foreground-color);
}
}
}
@ -367,7 +372,7 @@
height: fit-content;
border-radius: $br-8;
padding: $s-8;
color: var(--input-foreground-color);
color: var(--input-foreground-color-rest);
border: $s-1 solid transparent;
&:focus,
&:focus-within {
@ -393,14 +398,12 @@
border-radius: $br-circle;
}
.radio-label.with-image {
.radio-label-image {
@include smallTitleTipography;
display: grid;
grid-template-rows: auto auto 0px;
justify-items: center;
gap: 0;
height: $s-116;
width: $s-92;
border-radius: $br-8;
margin: 0;
border: 1px solid var(--color-background-tertiary);
@ -413,22 +416,29 @@
outline: none;
border: $s-1 solid var(--input-border-color-active);
}
.image-text {
color: var(--input-foreground-color-rest);
display: grid;
align-self: center;
margin-bottom: $s-16;
padding-inline: $s-8;
text-align: center;
}
}
.image-inside {
width: $s-60;
height: $s-48;
background-size: $s-48;
margin: $s-16;
background-size: 100%;
background-repeat: no-repeat;
background-position: center;
}
.icon-inside {
width: $s-60;
height: $s-48;
margin: $s-16;
@include flexCenter;
svg {
width: $s-60;
height: $s-48;
width: 40px;
height: 60px;
stroke: var(--icon-foreground);
fill: none;
}

View file

@ -34,6 +34,7 @@
.input-wrapper {
@extend .input-with-label;
@include bodySmallTypography;
}
.action-buttons {

View file

@ -81,6 +81,7 @@
}
.file-name-edit {
@extend .input-element;
@include bodySmallTypography;
flex-grow: 1;
}
.file-name-label {

View file

@ -540,5 +540,6 @@
.email-input {
@extend .input-base;
@include bodySmallTypography;
height: auto;
}

View file

@ -37,6 +37,7 @@
.group-name-input {
@extend .input-element-label;
@include bodySmallTypography;
margin-bottom: $s-8;
label {
@include flexColumn;

View file

@ -93,6 +93,7 @@
}
.input-wrapper {
@extend .input-element;
@include bodySmallTypography;
}
}
}

View file

@ -1,161 +0,0 @@
;; 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
(ns app.main.ui.onboarding
(:require-macros [app.main.style :as stl])
(:require
[app.common.data.macros :as dm]
[app.config :as cf]
[app.main.data.events :as ev]
[app.main.data.modal :as modal]
[app.main.data.users :as du]
[app.main.store :as st]
[app.main.ui.onboarding.newsletter]
[app.main.ui.onboarding.questions]
[app.main.ui.onboarding.team-choice]
[app.main.ui.onboarding.templates]
[app.util.i18n :as i18n :refer [tr]]
[app.util.timers :as tm]
[potok.v2.core :as ptk]
[rumext.v2 :as mf]))
;; --- ONBOARDING LIGHTBOX
(defn send-event
[event-name]
(st/emit! (ptk/event ::ev/event {::ev/name event-name
::ev/origin "dashboard"})))
(mf/defc onboarding-welcome
[{:keys [next] :as props}]
(let [go-next
(fn []
(send-event "onboarding-step1-continue")
(next))]
[:div {:class (stl/css :modal-container)}
[:div {:class (stl/css :modal-left)}
[:img {:src "images/welcomeilustration.svg"
:border "0"
:alt (tr "onboarding.welcome.alt")}]]
[:div {:class (stl/css :modal-right)}
[:div {:class (stl/css :release)}
"Version " (:main cf/version)]
[:h1 {:class (stl/css :modal-title)
:data-test "onboarding-welcome"}
(tr "onboarding-v2.welcome.title")]
[:p {:class (stl/css :modal-text)}
(tr "onboarding-v2.welcome.desc1")]
[:div {:class (stl/css :text-wrapper)}
[:div {:class (stl/css :property-title)}
[:a {:href "https://community.penpot.app/"
:target "_blank"
:on-click #(send-event "onboarding-community-link")}
(tr "onboarding-v2.welcome.desc2.title")]]
[:div {:class (stl/css :property-description)}
(tr "onboarding-v2.welcome.desc2")]]
[:div {:class (stl/css :text-wrapper)}
[:div {:class (stl/css :property-title)}
[:a {:href "https://help.penpot.app/contributing-guide/"
:target "_blank" :on-click #(send-event "onboarding-contributing-link")}
(tr "onboarding-v2.welcome.desc3.title")]]
[:div {:class (stl/css :property-description)}
(tr "onboarding-v2.welcome.desc3")]]
[:button {:on-click go-next
:class (stl/css :accept-btn)
:data-test "onboarding-next-btn"}
(tr "labels.continue")]]]))
(mf/defc onboarding-before-start
[{:keys [next] :as props}]
(let [go-next
(fn []
(send-event "onboarding-step2-continue")
(next))]
[:div {:class (stl/css :modal-container)}
[:div {:class (stl/css :modal-left)}
[:img {:src "images/beforeyoustartilustration.svg"
:border "0"
:alt (tr "onboarding.welcome.alt")}]]
[:div {:class (stl/css :modal-right)}
[:div {:class (stl/css :release)}
"Version " (:main cf/version)]
[:h1 {:class (stl/css :modal-title)
:data-test "onboarding-welcome"}
(tr "onboarding-v2.before-start.title")]
[:p {:class (stl/css :modal-text)}
(tr "onboarding-v2.before-start.desc1")]
[:div {:class (stl/css :text-wrapper)}
[:div {:class (stl/css :property-title)}
[:a {:class (stl/css :modal-link)
:href "https://help.penpot.app/user-guide/"
:target "_blank"
:on-click #(send-event "onboarding-user-guide-link")}
(tr "onboarding-v2.before-start.desc2.title")]]
[:div {:class (stl/css :property-description)}
(tr "onboarding-v2.before-start.desc2")]]
[:div {:class (stl/css :text-wrapper)}
[:div {:class (stl/css :property-title)}
[:a {:class (stl/css :modal-link)
:href "https://www.youtube.com/c/Penpot"
:target "_blank"
:on-click #(send-event "onboarding-video-tutorials-link")}
(tr "onboarding-v2.before-start.desc3.title")]]
[:div {:class (stl/css :property-description)}
(tr "onboarding-v2.before-start.desc3")]]
[:button {:on-click go-next
:class (stl/css :accept-btn)
:data-test "onboarding-next-btn"}
(tr "labels.continue")]]]))
(mf/defc onboarding-modal
{::mf/register modal/components
::mf/register-as :onboarding}
[_]
(let [slide (mf/use-state :start)
klass (mf/use-state "fadeInDown")
navigate
(mf/use-fn #(reset! slide %))
skip
(mf/use-fn
(fn []
(st/emit! (modal/hide)
(du/mark-onboarding-as-viewed))
(cond
(contains? cf/flags :onboarding-questions)
(modal/show! {:type :onboarding-questions})
(contains? cf/flags :onboarding-newsletter)
(modal/show! {:type :onboarding-newsletter})
(contains? cf/flags :onboarding-team)
(modal/show! {:type :onboarding-team}))))
onboarding-a-b-test? (cf/external-feature-flag "signup-background" "test")]
(mf/with-effect [@slide]
(when (not= :start @slide)
(reset! klass "fadeIn"))
(let [sem (tm/schedule 300 #(reset! klass nil))]
(fn []
(reset! klass nil)
(tm/dispose! sem))))
[:div {:class (stl/css-case :modal-overlay true
:onboarding-a-b-test onboarding-a-b-test?)}
[:div.animated {:class (dm/str @klass " " (stl/css :animated))}
(case @slide
:start [:& onboarding-welcome {:next #(navigate :opensource)}]
:opensource [:& onboarding-before-start {:next skip}])]]))

View file

@ -1,86 +0,0 @@
// 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
@import "refactor/common-refactor.scss";
.modal-overlay {
@extend .modal-overlay-base;
}
.modal-container {
@extend .modal-container-base;
position: relative;
display: grid;
grid-template-columns: auto auto;
gap: $s-32;
padding-inline: $s-100;
padding-block-start: $s-100;
padding-block-end: $s-72;
margin: 0;
width: $s-960;
height: $s-632;
max-width: $s-960;
max-height: $s-632;
}
.modal-left {
width: $s-240;
margin-block-end: $s-64;
img {
width: $s-240;
height: 100%;
border-radius: $br-8 0 0 $br-8;
}
}
.modal-right {
display: grid;
grid-template-columns: 1fr;
grid-template-rows: $s-40 auto auto auto $s-32;
gap: $s-24;
position: relative;
}
.release {
@include bodySmallTypography;
position: absolute;
top: calc(-1 * $s-28);
right: 0;
padding: $s-8;
color: var(--modal-text-foreground-color);
}
.modal-title {
@include bigTitleTipography;
color: var(--modal-title-foreground-color);
}
.modal-text,
.property-description {
@include bodyLargeTypography;
margin: 0;
color: var(--modal-text-foreground-color);
}
.modal-link {
@include bodyLargeTypography;
color: var(--modal-link-foreground-color);
margin: 0;
}
.text-wrapper {
@include flexColumn;
}
.property-title a {
@include medTitleTipography;
color: var(--modal-title-foreground-color);
}
.accept-btn {
@extend .modal-accept-btn;
justify-self: flex-end;
}

View file

@ -25,7 +25,7 @@
[{:keys [form step on-next on-prev children class] :as props}]
[:& fm/form {:form form :on-submit on-next :class (dm/str class " " (stl/css :form-wrapper))}
[:div {:class (stl/css :paginator)} (str/ffmt "%/4" step)]
[:div {:class (stl/css :paginator)} (str/ffmt "%/5" step)]
children
@ -36,107 +36,86 @@
:on-click on-prev} (tr "questions.previous")])
[:> fm/submit-button*
{:label (if (< step 4) (tr "questions.next") (tr "questions.start"))
{:label (if (< step 5) (tr "questions.next") (tr "questions.start"))
:class (stl/css :next-button)}]]])
(s/def ::questions-form-step-1
(s/keys :req-un [::planning]))
(mf/defc step-1
[{:keys [on-next form] :as props}]
[:& step-container {:form form :step 1 :on-next on-next :class (stl/css :step-1)}
[:img {:class (stl/css :header-image)
:src "images/form/use-for-1.png" :alt (tr "questions.lets-get-started")}]
[:h1 {:class (stl/css :modal-title)} (tr "questions.lets-get-started")]
[:p {:class (stl/css :modal-text)} (tr "questions.your-feedback-will-help-us")]
[:div {:class (stl/css :modal-question)}
[:h3 {:class (stl/css :modal-subtitle)} (tr "questions.questions-how-are-you-planning-to-use-penpot")]
[:& fm/select
{:options [{:label (tr "questions.select-option")
:value "" :key "questions-how-are-you-planning-to-use-penpot"
:disabled true}
{:label (tr "questions.discover-more-about-penpot")
:value "discover-more-about-penpot"
:key "discover-more-about-penpot"}
{:label (tr "questions.test-penpot-to-see-if-its-a-fit-for-team")
:value "test-penpot-to-see-if-its-a-fit-for-team"
:key "test-penpot-to-see-if-its-a-fit-for-team"}
{:label (tr "questions.start-to-work-on-my-project")
:value "start-to-work-on-my-project"
:key "start-to-work-on-my-project"}
{:label (tr "questions.get-the-code-from-my-team-project")
:value "get-the-code-from-my-team-project"
:key "get-the-code-from-my-team-project"}
{:label (tr "questions.leave-feedback-for-my-team-project")
:value "leave-feedback-for-my-team-project"
:key "leave-feedback-for-my-team-project"}
{:label (tr "questions.work-in-concept-ideas")
:value "work-in-concept-ideas"
:key "work-in-concept-ideas"}
{:label (tr "questions.try-out-before-using-penpot-on-premise")
:value "try-out-before-using-penpot-on-premise"
:key "try-out-before-using-penpot-on-premise"}]
:default ""
:name :planning
:dropdown-class (stl/css :question-dropdown)}]]])
(s/def ::questions-form-step-2
(s/keys :req-un [::experience-branding-illustrations-marketing-pieces
::experience-interface-design-visual-assets-design-systems
::experience-interface-wireframes-user-journeys-flows-navigation-trees]))
(mf/defc step-2
[{:keys [on-next on-prev form] :as props}]
[:& step-container {:form form :step 2 :on-next on-next :on-prev on-prev :class (stl/css :step-2)}
[:h1 {:class (stl/css :modal-title)}
(tr "questions.describe-your-experience-working-on")]
[:div {:class (stl/css-case :modal-question true
:question-centered true)}
[:div {:class (stl/css-case :modal-subtitle true
:centered true)}
(tr "branding-illustrations-marketing-pieces")]
[:& fm/radio-buttons {:options [{:label (tr "questions.none") :value "none"}
{:label (tr "questions.some") :value "some"}
{:label (tr "questions.a-lot") :value "a-lot"}]
:name :experience-branding-illustrations-marketing-pieces
:class (stl/css :radio-btns)}]]
[:div {:class (stl/css-case :modal-question true
:question-centered true)}
[:div {:class (stl/css-case :modal-subtitle true
:centered true)}
(tr "questions.interface-design-visual-assets-design-systems")]
[:& fm/radio-buttons {:options [{:label (tr "questions.none") :value "none"}
{:label (tr "questions.some") :value "some"}
{:label (tr "questions.a-lot") :value "a-lot"}]
:name :experience-interface-design-visual-assets-design-systems
:class (stl/css :radio-btns)}]]
[:div {:class (stl/css-case :modal-question true
:question-centered true)}
[:div {:class (stl/css-case :modal-subtitle true
:centered true)}
(tr "questions.wireframes-user-journeys-flows-navigation-trees")]
[:& fm/radio-buttons {:options [{:label (tr "questions.none") :value "none"}
{:label (tr "questions.some") :value "some"}
{:label (tr "questions.a-lot") :value "a-lot"}]
:name :experience-interface-wireframes-user-journeys-flows-navigation-trees
:class (stl/css :radio-btns)}]]])
(s/def ::questions-form-step-3
(s/keys :req-un [::experience-design-tool]
:opt-un [::experience-design-tool-other]))
(s/keys :req-un [::planning
::penpot-use]
:opt-un [::planning-other]))
(defn- step-1-form-validator
[errors data]
(let [planning (-> (:planning data) (str/trim))]
(let [planning (-> (:planning data) (str/trim))
planning-other (-> (:planning-other data) str/trim)]
(cond-> errors
(and (= planning-other "other") (= 0 (count planning-other)))
(assoc :planning-other {:code "missing"})
(= planning "")
(assoc :planning {:code "missing"}))))
(defn- step-3-form-validator
(mf/defc step-1
[{:keys [on-next form] :as props}]
(let [use-ops-randomized (mf/with-memo [] (shuffle [{:label (tr "questions.use-work") :value "use-work"}
{:label (tr "questions.use-education") :value "use-education"}
{:label (tr "questions.use-personal") :value "use-personal"}]))
planning-ops (mf/with-memo [] (shuffle [{:label (tr "questions.select-option")
:value "" :key "questions-what-brings-you-here"
:disabled true}
{:label (tr "questions.reasons.exploring")
:value "discover-more-about-penpot"
:key "discover-more-about-penpot"}
{:label (tr "questions.reasons.fit")
:value "test-penpot-to-see-if-its-a-fit-for-team"
:key "test-penpot-to-see-if-its-a-fit-for-team"}
{:label (tr "questions.reasons.alternative")
:value "alternative-to-figma"
:key "alternative-to-figma"}
{:label (tr "questions.reasons.testing")
:value "try-out-before-using-penpot-on-premise"
:key "try-out-before-using-penpot-on-premise"}]))
planning-ops-randomized (conj planning-ops {:label (tr "questions.other-short") :value "other"})
planning (dm/get-in @form [:data :planning])]
[:& step-container {:form form :step 1 :on-next on-next :class (stl/css :step-1)}
[:img {:class (stl/css :header-image)
:src "images/form/use-for-1.png"
:alt (tr "questions.lets-get-started")}]
[:h1 {:class (stl/css :modal-title)}
(tr "questions.step1-title")]
[:p {:class (stl/css :modal-text)}
(tr "questions.step1-subtitle")]
[:div {:class (stl/css :modal-question)}
[:h3 {:class (stl/css :modal-subtitle)} (tr "questions.step1-question1")]
[:& fm/radio-buttons {:options use-ops-randomized
:name :penpot-use
:class (stl/css :radio-btns)}]
[:h3 {:class (stl/css :modal-subtitle)} (tr "questions.step1-question2")]
[:& fm/select
{:options planning-ops-randomized
:select-class (stl/css :select-class)
:default ""
:name :planning
:dropdown-class (stl/css :question-dropdown)}]
(when (= planning "other")
[:& fm/input {:name :planning-other
:class (stl/css :input-spacing)
:placeholder (tr "questions.other")
:label ""}])]]))
(s/def ::questions-form-step-2
(s/keys :req-un [::experience-design-tool]
:opt-un [::experience-design-tool-other]))
(defn- step-2-form-validator
[errors data]
(let [experience-design-tool (:experience-design-tool data)
experience-design-tool-other (-> (:experience-design-tool-other data) str/trim)]
@ -144,9 +123,17 @@
(and (= experience-design-tool "other") (= 0 (count experience-design-tool-other)))
(assoc :experience-design-tool-other {:code "missing"}))))
(mf/defc step-3
(mf/defc step-2
[{:keys [on-next on-prev form] :as props}]
(let [experience-design-tool (dm/get-in @form [:clean-data :experience-design-tool])
(let [design-tool-options (mf/with-memo [] (shuffle [{:label (tr "questions.figma") :img-width "48px" :img-height "60px" :value "figma" :image "images/form/figma.png"}
{:label (tr "questions.sketch") :img-width "48px" :img-height "60px" :value "sketch" :image "images/form/sketch.png"}
{:label (tr "questions.adobe-xd") :img-width "48px" :img-height "60px" :value "adobe-xd" :image "images/form/adobe-xd.png"}
{:label (tr "questions.canva") :img-width "48px" :img-height "60px" :value "canva" :image "images/form/canva.png"}
{:label (tr "questions.invision") :img-width "48px" :img-height "60px" :value "invision" :image "images/form/invision.png"}]))
design-tool-options-randomized (conj design-tool-options {:label (tr "questions.other-short") :value "other" :icon i/curve})
experience-design-tool (dm/get-in @form [:clean-data :experience-design-tool])
on-design-tool-change
(fn [_ _]
(let [experience-design-tool (dm/get-in @form [:clean-data :experience-design-tool])]
@ -155,71 +142,98 @@
(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 3 :on-next on-next :on-prev on-prev :class (stl/css :step-3)}
[:& step-container {:form form :step 2 :on-next on-next :on-prev on-prev :class (stl/css :step-2)}
[:h1 {:class (stl/css :modal-title)}
(tr "question.design-tool-more-experienced-with")]
(tr "question.design-tool-more-used")]
[:div {:class (stl/css :radio-wrapper)}
[:& fm/radio-buttons {:options [{:label (tr "questions.figma") :value "figma" :image "images/form/figma.png" :area "image1"}
{:label (tr "questions.sketch") :value "sketch" :image "images/form/sketch.png" :area "image2"}
{:label (tr "questions.adobe-xd") :value "adobe-xd" :image "images/form/adobe-xd.png" :area "image3"}
{:label (tr "questions.canva") :value "canva" :image "images/form/canva.png" :area "image4"}
{:label (tr "questions.invision") :value "invision" :image "images/form/invision.png" :area "image5"}
{:label (tr "questions.never-used-one") :area "image6" :value "never-used-a-tool" :icon i/curve}
{:label (tr "questions.other") :value "other" :area "other"}]
:name :experience-design-tool
:image true
:class (stl/css :image-radio)
:on-change on-design-tool-change}]
[:& fm/image-radio-buttons {:options design-tool-options-randomized
:img-width "48px"
:img-height "60px"
:name :experience-design-tool
:image true
:class (stl/css :image-radio)
:on-change on-design-tool-change}]
[:& fm/input {:name :experience-design-tool-other
:class (stl/css :input-spacing)
:placeholder (tr "questions.other")
:label ""
:disabled (not= experience-design-tool "other")}]]]))
(when (= experience-design-tool "other")
[:& fm/input {:name :experience-design-tool-other
:class (stl/css :input-spacing)
:placeholder (tr "questions.other")
:label ""}])]]))
(s/def ::questions-form-step-4
(s/keys :req-un [::team-size ::role]
:opt-un [::role-other]))
(s/def ::questions-form-step-3
(s/keys :req-un [::team-size ::role ::responsability]
:opt-un [::role-other ::responsability-other]))
(defn- step-4-form-validator
(defn- step-3-form-validator
[errors data]
(let [role (:role data)
role-other (-> (:role-other data) str/trim)]
role-other (-> (:role-other data) str/trim)
responsability (:responsability data)
responsability-other (-> (:responsability-other data) str/trim)]
(cond-> errors
(and (= role "other") (= 0 (count role-other)))
(assoc :role-other {:code "missing"}))))
(assoc :role-other {:code "missing"})
(mf/defc step-4
(and (= responsability "other") (= 0 (count responsability-other)))
(assoc :responsability-other {:code "missing"}))))
(mf/defc step-3
[{:keys [on-next on-prev form] :as props}]
(let [role (dm/get-in @form [:data :role])
on-role-change
(fn [_ _]
(let [experience-design-tool (dm/get-in @form [:clean-data :experience-design-tool])]
(when (not= experience-design-tool "other")
(do
(swap! form d/dissoc-in [:data :role-other])
(swap! form d/dissoc-in [:errors :role-other])))))]
(let [role-ops (mf/with-memo [] (shuffle [{:label (tr "questions.select-option") :value "" :key "role" :disabled true}
{:label (tr "questions.work-type.ux") :value "designer" :key "designer"}
{:label (tr "questions.work-type.dev") :value "developer" :key "developer"}
{:label (tr "questions.work-type.student") :value "student-teacher" :key "student"}
{:label (tr "questions.work-type.graphic") :value "graphic-design" :key "design"}
{:label (tr "questions.work-type.marketing") :value "marketing" :key "marketing"}
{:label (tr "questions.work-type.product") :value "manager" :key "manager"}]))
role-ops-randomized (conj role-ops {:label (tr "questions.other-short") :value "other"})
[:& step-container {:form form :step 4 :on-next on-next :on-prev on-prev :class (stl/css :step-4)}
[:h1 {:class (stl/css :modal-title)} (tr "questions.role")]
[:div {:class (stl/css :radio-wrapper)}
[:& fm/radio-buttons {:options [{:label (tr "questions.designer") :value "designer"}
{:label (tr "questions.developer") :value "developer"}
{:label (tr "questions.manager") :value "manager"}
{:label (tr "questions.founder") :value "founder"}
{:label (tr "questions.marketing") :value "marketing"}
{:label (tr "questions.student-teacher") :value "student-teacher"}
{:label (tr "questions.other") :value "other"}]
:name :role
:on-change on-role-change}]
[:& fm/input {:name :role-other
:class (stl/css :input-spacing)
:label ""
:placeholder (tr "questions.other")
:disabled (not= role "other")}]]
responsability-options (mf/with-memo [] (shuffle [{:label (tr "questions.select-option") :value "" :key "responsability" :disabled true}
{:label (tr "questions.role.team-leader") :value "team-leader"}
{:label (tr "questions.role.team-member") :value "team-member"}
{:label (tr "questions.role.freelancer") :value "freelancer"}
{:label (tr "questions.role.founder") :value "ceo-founder"}
{:label (tr "questions.role.director") :value "director"}
{:label (tr "questions.student-teacher") :value "student-teacher"}]))
responsability-options-randomized (conj responsability-options {:label (tr "questions.other-short") :value "other"})
role (dm/get-in @form [:data :role])
responsability (dm/get-in @form [:data :responsability])]
[:& step-container {:form form :step 3 :on-next on-next :on-prev on-prev :class (stl/css :step-3)}
[:h1 {:class (stl/css :modal-title)} (tr "questions.step3-title")]
[:div {:class (stl/css :modal-question)}
[:h3 {:class (stl/css :modal-subtitle)} (tr "questions.step3.question1")]
[:& fm/select {:options role-ops-randomized
:select-class (stl/css :select-class)
:default ""
:name :role}]
(when (= role "other")
[:& fm/input {:name :role-other
:class (stl/css :input-spacing)
:placeholder (tr "questions.other")
:label ""}])]
[:div {:class (stl/css :modal-question)}
[:h3 {:class (stl/css :modal-subtitle)} (tr "questions.team-size")]
[:h3 {:class (stl/css :modal-subtitle)} (tr "questions.step3.question2")]
[:& fm/select {:options responsability-options-randomized
:select-class (stl/css :select-class)
:default ""
:name :responsability}]
(when (= responsability "other")
[:& fm/input {:name :responsability-other
:class (stl/css :input-spacing)
:placeholder (tr "questions.other")
:label ""}])]
[:div {:class (stl/css :modal-question)}
[:h3 {:class (stl/css :modal-subtitle)} (tr "questions.company-size")]
[:& fm/select {:options [{:label (tr "questions.select-option") :value "" :key "team-size" :disabled true}
{:label (tr "questions.more-than-50") :value "more-than-50" :key "more-than-50"}
{:label (tr "questions.31-50") :value "31-50" :key "31-50"}
@ -228,10 +242,102 @@
{:label (tr "questions.freelancer") :value "freelancer" :key "freelancer"}
{:label (tr "questions.personal-project") :value "personal-project" :key "personal-project"}]
:default ""
:select-class (stl/css :select-class)
:name :team-size}]]]))
;; NOTE: we don't register it on registry modal because we reference
;; this modal directly on the ui namespace.
(s/def ::questions-form-step-4
(s/keys :req-un [::start]
:opt-un [::start-other]))
(defn- step-4-form-validator
[errors data]
(let [start (:start data)
start-other (-> (:start-other data) str/trim)]
(cond-> errors
(and (= start "other") (= 0 (count start-other)))
(assoc :start-other {:code "missing"}))))
(mf/defc step-4
[{:keys [on-next on-prev form] :as props}]
(let [start-options (mf/with-memo [] (shuffle [{:label (tr "questions.starting-ui") :value "ui" :image "images/form/Design.png"}
{:label (tr "questions.starting-wireframing") :value "wireframing" :image "images/form/templates.png"}
{:label (tr "questions.starting-prototyping") :value "prototyping" :image "images/form/Prototype.png"}
{:label (tr "questions.starting-ds") :value "ds" :image "images/form/components.png"}
{:label (tr "questions.starting-code") :value "code" :image "images/form/design-and-dev.png"}]))
start-options-randomized (conj start-options {:label (tr "questions.other-short") :value "other" :icon i/curve})
start (dm/get-in @form [:data :start])
on-start-change
(fn [_ _]
(let [start (dm/get-in @form [:clean-data :start])]
(when (not= start "other")
(do
(swap! form d/dissoc-in [:data :start-other])
(swap! form d/dissoc-in [:errors :start-other])))))]
[:& step-container {:form form :step 4 :on-next on-next :on-prev on-prev :class (stl/css :step-4)}
[:h1 {:class (stl/css :modal-title)} (tr "questions.step4-title")]
[:div {:class (stl/css :radio-wrapper)}
[:& fm/image-radio-buttons {:options start-options-randomized
:img-width "159px"
:img-height "120px"
:class (stl/css :image-radio)
:name :start
:on-change on-start-change}]
(when (= start "other")
[:& fm/input {:name :start-other
:class (stl/css :input-spacing)
:label ""
:placeholder (tr "questions.other")
:disabled (not= start "other")}])]]))
(s/def ::questions-form-step-5
(s/keys :req-un [::knowledge]
:opt-un [::knowledge-other]))
(defn- step-5-form-validator
[errors data]
(let [knowledge (:knowledge data)
knowledge-other (-> (:knowledge-other data) str/trim)]
(cond-> errors
(and (= knowledge "other") (= 0 (count knowledge-other)))
(assoc :knowledge-other {:code "missing"}))))
(mf/defc step-5
[{:keys [on-next on-prev form] :as props}]
(let [knowledge-options (mf/with-memo [] (shuffle [{:label (tr "questions.knowledge.youtube") :value "Youtube"}
{:label (tr "questions.knowledge.event") :value "event"}
{:label (tr "questions.knowledge.search") :value "search"}
{:label (tr "questions.knowledge.social") :value "social"}
{:label (tr "questions.knowledge.article") :value "article"}]))
knowledge-options-randomized (conj knowledge-options {:label (tr "questions.other-short") :value "other"})
knowledge (dm/get-in @form [:data :knowledge])
on-knowledge-change
(fn [_ _]
(let [experience-design-tool (dm/get-in @form [:clean-data :experience-design-tool])]
(when (not= experience-design-tool "other")
(do
(swap! form d/dissoc-in [:data :knowledge-other])
(swap! form d/dissoc-in [:errors :knowledge-other])))))]
[:& step-container {:form form :step 5 :on-next on-next :on-prev on-prev :class (stl/css :step-5)}
[:h1 {:class (stl/css :modal-title)} (tr "questions.step5-title")]
[:div {:class (stl/css :radio-wrapper)}
[:& fm/radio-buttons {:options knowledge-options-randomized
:class (stl/css :radio-btns)
:name :knowledge
:on-change on-knowledge-change}]
(when (= knowledge "other")
[:& fm/input {:name :knowledge-other
:class (stl/css :input-spacing)
:label ""
:placeholder (tr "questions.other")
:disabled (not= knowledge "other")}])]]))
(mf/defc questions-modal
{::mf/register modal/components
@ -247,9 +353,12 @@
:initial {}
:validators [step-1-form-validator]
:spec ::questions-form-step-1)
step-2-form (fm/use-form
:initial {}
:validators [step-2-form-validator]
:spec ::questions-form-step-2)
step-3-form (fm/use-form
:initial {}
:validators [step-3-form-validator]
@ -260,6 +369,11 @@
:validators [step-4-form-validator]
:spec ::questions-form-step-4)
step-5-form (fm/use-form
:initial {}
:validators [step-5-form-validator]
:spec ::questions-form-step-5)
on-next
(mf/use-fn
(fn [form]
@ -298,4 +412,5 @@
1 [:& step-1 {:on-next on-next :on-prev on-prev :form step-1-form}]
2 [:& step-2 {:on-next on-next :on-prev on-prev :form step-2-form}]
3 [:& step-3 {:on-next on-next :on-prev on-prev :form step-3-form}]
4 [:& step-4 {:on-next on-submit :on-prev on-prev :form step-4-form}])]]))
4 [:& step-4 {:on-next on-next :on-prev on-prev :form step-4-form}]
5 [:& step-5 {:on-next on-submit :on-prev on-prev :form step-5-form}])]]))

View file

@ -11,9 +11,9 @@
}
.modal-container {
max-width: $s-744;
max-width: $s-960;
max-height: fit-content;
width: $s-744;
width: fit-content;
padding-inline: $s-100;
padding-block-start: $s-40;
padding-block-end: $s-72;
@ -47,15 +47,15 @@
@extend .modal-cancel-btn;
}
.radio-btns label,
.select-class span {
@include bodyMediumTypography;
}
// STEP 1
// .step-1 {
// max-height: $s-468;
// height: $s-468;
// }
.header-image {
height: $s-112;
height: $s-60;
width: auto;
margin-inline-start: auto;
}
@ -81,9 +81,15 @@
}
// STEP-2
.step-1,
.step-2,
.step-3,
.step-5 {
max-width: $s-540;
width: $s-540;
}
.step-2 {
grid-template-rows: $s-20 auto auto auto auto $s-32;
grid-template-rows: $s-20 auto auto $s-32;
}
.modal-question {
@ -103,36 +109,36 @@
.radio-wrapper {
display: grid;
grid-template-columns: 1fr;
gap: $s-8;
gap: $s-16;
}
// STEP-3
.step-3 {
grid-template-rows: $s-20 auto auto $s-32;
grid-template-rows: $s-20 auto auto auto auto $s-32;
}
.image-radio {
display: grid;
grid-template-rows: 1fr 1fr $s-32;
grid-template-columns: $s-88 $s-92 $s-92 $s-92 $s-88;
grid-template-areas:
". image1 image2 image3 ."
". image4 image5 image6 ."
"other other other other other";
grid-template-rows: 1fr 1fr;
grid-template-columns: $s-92 $s-92 $s-92;
row-gap: $s-16;
column-gap: $s-24;
justify-content: center;
}
.input-spacing {
height: $s-32;
width: calc(100% - $s-24);
margin-inline-start: $s-24;
width: 100%;
margin-block-end: $s-8;
}
.input-spacing input {
@include bodyMediumTypography;
}
// STEP-4
.step-4 {
grid-template-rows: $s-20 auto auto auto $s-32;
grid-template-rows: $s-20 auto auto $s-32;
row-gap: $s-16;
}

View file

@ -160,6 +160,7 @@
.custom-input-token {
@extend .input-element;
@include bodySmallTypography;
margin: 0;
flex-grow: 1;
&:focus {

View file

@ -92,6 +92,7 @@
.suffix-input {
@extend .input-element;
@include bodySmallTypography;
grid-column: span 3;
}

View file

@ -63,6 +63,7 @@
.input-text {
@extend .input-element;
@include bodySmallTypography;
color: var(--input-foreground-color-active);
padding-left: $s-8;
margin: 0;

View file

@ -17,6 +17,7 @@
@include flexRow;
.input-wrapper {
@extend .input-element;
@include bodySmallTypography;
width: $s-84;
display: flex;
align-items: baseline;
@ -26,6 +27,7 @@
@include flexRow;
.input-wrapper {
@extend .input-element;
@include bodySmallTypography;
width: $s-84;
&.hex {
width: $s-172;

View file

@ -36,6 +36,7 @@
.input-wrapper {
@extend .input-with-label;
@include bodySmallTypography;
label {
text-transform: none;
}

View file

@ -49,6 +49,7 @@
}
.input-wrapper {
@extend .input-with-label;
@include bodySmallTypography;
margin-bottom: $s-8;
}
.action-buttons {

View file

@ -100,6 +100,7 @@
.second-row {
@extend .input-element;
@include bodySmallTypography;
width: $s-92;
.label {
padding-left: $s-8;

View file

@ -92,6 +92,7 @@
.suffix-input {
grid-column: span 3;
@extend .input-element;
@include bodySmallTypography;
}
.export-btn {

View file

@ -77,6 +77,7 @@
border-radius: 0 $br-8 $br-8 0;
.numeric-input {
@extend .input-base;
@include bodySmallTypography;
}
}
.editable-select-wrapper {
@ -93,6 +94,7 @@
border: $s-1 solid var(--input-border-color);
.numeric-input {
@extend .input-base;
@include bodySmallTypography;
margin: 0;
padding: 0;
}
@ -196,6 +198,7 @@
}
.height {
@extend .input-element;
@include bodySmallTypography;
width: $s-108;
.icon-text {
padding-top: $s-1;
@ -204,6 +207,7 @@
.gutter,
.margin {
@extend .input-element;
@include bodySmallTypography;
width: $s-108;
.icon {
&.rotated svg {

View file

@ -33,6 +33,7 @@
.area-input {
@extend .input-element;
@include bodySmallTypography;
width: 100%;
padding: $s-8;
}
@ -51,6 +52,7 @@
.coord-input {
@extend .input-element;
@include bodySmallTypography;
border-radius: 0 $br-8 $br-8 0;
border-left: $s-1 solid var(--panel-background-color);
}

View file

@ -143,6 +143,7 @@
}
.input-element-wrapper {
@extend .input-element;
@include bodySmallTypography;
grid-area: content;
}
.buttons-wrapper {
@ -319,6 +320,7 @@
.flow-input {
@extend .input-base;
@include bodySmallTypography;
background-color: transparent;
height: $s-28;
}

View file

@ -19,6 +19,7 @@
}
.input {
@extend .input-element;
@include bodySmallTypography;
width: $s-60;
}
.actions {

View file

@ -84,6 +84,7 @@
gap: $s-4;
.column-gap {
@extend .input-element;
@include bodySmallTypography;
width: $s-108;
&.disabled {
@extend .disabled-input;
@ -91,6 +92,7 @@
}
.row-gap {
@extend .input-element;
@include bodySmallTypography;
width: $s-108;
&.disabled {
@extend .disabled-input;
@ -113,6 +115,7 @@
.padding-simple {
@extend .input-element;
@include bodySmallTypography;
max-width: $s-108;
}
}
@ -124,6 +127,7 @@
.padding-multiple {
@extend .input-element;
@include bodySmallTypography;
max-width: $s-108;
}
}
@ -239,6 +243,7 @@
.track-info-value {
@extend .input-element;
@include bodySmallTypography;
border-radius: 0;
border-right: $s-1 solid var(--panel-background-color);
}

View file

@ -58,6 +58,7 @@
.z-index-wrapper {
@extend .input-element;
@include bodySmallTypography;
width: $s-60;
}
@ -94,6 +95,7 @@
.vertical-margin,
.horizontal-margin {
@extend .input-element;
@include bodySmallTypography;
width: $s-108;
}
}
@ -109,6 +111,7 @@
.left-margin,
.right-margin {
@extend .input-element;
@include bodySmallTypography;
width: $s-108;
}
@ -127,6 +130,7 @@
.layout-item-max-w,
.layout-item-max-h {
@extend .input-element;
@include bodySmallTypography;
width: $s-108;
.icon-text {
justify-content: flex-start;

View file

@ -114,6 +114,7 @@
.height,
.width {
@extend .input-element;
@include bodySmallTypography;
width: $s-108;
.icon-text {
padding-top: $s-1;
@ -145,6 +146,7 @@
.x-position,
.y-position {
@extend .input-element;
@include bodySmallTypography;
width: $s-108;
.icon-text {
padding-top: $s-1;
@ -163,6 +165,7 @@
.rotation {
@extend .input-element;
@include bodySmallTypography;
width: $s-108;
.icon-text {
padding-top: $s-1;
@ -181,6 +184,7 @@
.radius-1 {
@extend .input-element;
@include bodySmallTypography;
width: $s-108;
}
@ -190,6 +194,7 @@
gap: $s-4;
.small-input {
@extend .input-element;
@include bodySmallTypography;
width: $s-52;
}
}

View file

@ -114,6 +114,7 @@
.spread-input,
.offset-y-input {
@extend .input-element;
@include bodySmallTypography;
width: $s-60;
min-width: $s-60;
align-items: baseline;

View file

@ -37,6 +37,7 @@
.attr-input {
@extend .input-element;
@include bodySmallTypography;
width: $s-124;
}

View file

@ -308,6 +308,7 @@
.line-height,
.letter-spacing {
@extend .input-element;
@include bodySmallTypography;
.icon {
@include flexCenter;
width: $s-28;
@ -339,6 +340,7 @@
padding: $s-8;
.numeric-input {
@extend .input-base;
@include bodySmallTypography;
padding: 0;
}
}

View file

@ -41,6 +41,7 @@
.color-name-wrapper {
@extend .input-element;
@include bodySmallTypography;
flex-grow: 1;
width: 100%;
min-width: 0;
@ -166,6 +167,7 @@
.opacity-element-wrapper {
@extend .input-element;
@include bodySmallTypography;
width: $s-60;
border-radius: 0 $br-8 $br-8 0;
.opacity-input {

View file

@ -12,6 +12,7 @@
@include flexRow;
.stroke-width-input-element {
@extend .input-element;
@include bodySmallTypography;
width: $s-60;
}
.select-wrapper {