From 0b29767c9581d0296fd1f8a7b553a27f01d25ca8 Mon Sep 17 00:00:00 2001 From: Florian Schroedl Date: Fri, 30 Aug 2024 11:51:21 +0200 Subject: [PATCH 01/19] Add color token --- common/src/app/common/types/token.cljc | 9 ++++++++- .../app/main/ui/workspace/tokens/changes.cljs | 5 +++++ .../main/ui/workspace/tokens/context_menu.cljs | 4 ++-- .../src/app/main/ui/workspace/tokens/form.cljs | 16 ++++++++++------ .../src/app/main/ui/workspace/tokens/modals.cljs | 6 ++++++ .../app/main/ui/workspace/tokens/sidebar.cljs | 1 + .../ui/workspace/tokens/style_dictionary.cljs | 9 +++++++-- .../src/app/main/ui/workspace/tokens/token.cljs | 9 +++++++++ .../main/ui/workspace/tokens/token_types.cljs | 8 ++++++++ .../src/app/main/ui/workspace/tokens/update.cljs | 1 + 10 files changed, 57 insertions(+), 11 deletions(-) diff --git a/common/src/app/common/types/token.cljc b/common/src/app/common/types/token.cljc index 6de8f9c29..ed63908ab 100644 --- a/common/src/app/common/types/token.cljc +++ b/common/src/app/common/types/token.cljc @@ -35,8 +35,8 @@ (def token-types #{:boolean :border-radius - :stroke-width :box-shadow + :color :dimensions :numeric :opacity @@ -45,6 +45,7 @@ :sizing :spacing :string + :stroke-width :typography}) (defn valid-token-type? @@ -66,6 +67,12 @@ [:description {:optional true} :string] [:modified-at {:optional true} ::sm/inst]]) +(sm/register! ::color + [:map + [:color {:optional true} token-name-ref]]) + +(def color-keys (schema-keys ::color)) + (sm/register! ::border-radius [:map [:rx {:optional true} token-name-ref] diff --git a/frontend/src/app/main/ui/workspace/tokens/changes.cljs b/frontend/src/app/main/ui/workspace/tokens/changes.cljs index 95243ee51..57d09f703 100644 --- a/frontend/src/app/main/ui/workspace/tokens/changes.cljs +++ b/frontend/src/app/main/ui/workspace/tokens/changes.cljs @@ -8,6 +8,7 @@ (:require [app.common.types.shape.radius :as ctsr] [app.common.types.token :as ctt] + [app.main.data.workspace.colors :as wdc] [app.main.data.workspace :as udw] [app.main.data.workspace.shape-layout :as dwsl] [app.main.data.workspace.shapes :as dwsh] @@ -123,6 +124,10 @@ {:reg-objects? true :attrs [:strokes]})) +(defn update-color + [value shape-ids] + (wdc/change-fill shape-ids {:color (str "#" value)} 0)) + (defn update-shape-dimensions [value shape-ids attributes] (ptk/reify ::update-shape-dimensions ptk/WatchEvent diff --git a/frontend/src/app/main/ui/workspace/tokens/context_menu.cljs b/frontend/src/app/main/ui/workspace/tokens/context_menu.cljs index 1eba57205..6e4156d03 100644 --- a/frontend/src/app/main/ui/workspace/tokens/context_menu.cljs +++ b/frontend/src/app/main/ui/workspace/tokens/context_menu.cljs @@ -222,10 +222,10 @@ (defn selection-actions [{:keys [type token] :as context-data}] (let [with-actions (get shape-attribute-actions-map (or type (:type token))) - attribute-actions (with-actions context-data)] + attribute-actions (if with-actions (with-actions context-data) [])] (concat attribute-actions - [:separator] + (when (seq attribute-actions) [:separator]) (default-actions context-data)))) ;; Components ------------------------------------------------------------------ diff --git a/frontend/src/app/main/ui/workspace/tokens/form.cljs b/frontend/src/app/main/ui/workspace/tokens/form.cljs index d58cca142..cc30768a6 100644 --- a/frontend/src/app/main/ui/workspace/tokens/form.cljs +++ b/frontend/src/app/main/ui/workspace/tokens/form.cljs @@ -101,15 +101,19 @@ Token names should only contain letters and digits separated by . characters.")} :else (let [token-id (or (:id token) (random-uuid)) new-tokens (update tokens token-name merge {:id token-id :value input - :name token-name})] - (-> (sd/resolve-tokens+ new-tokens {:names-map? true}) + :name token-name + :type (:type token)})] + (-> (sd/resolve-tokens+ new-tokens {:names-map? true + :debug? true}) (p/then (fn [resolved-tokens] + (js/console.log "resolved-tokens" resolved-tokens) (let [{:keys [errors resolved-value] :as resolved-token} (get resolved-tokens token-name)] (cond resolved-value (p/resolved resolved-token) (sd/missing-reference-error? errors) (p/rejected :error/token-missing-reference) - :else (p/rejected :error/unknown-error)))))))))) + :else (p/rejected :error/unknown-error))))) + (p/catch js/console.log)))))) (defn use-debonced-resolve-callback "Resolves a token values using `StyleDictionary`. @@ -143,8 +147,8 @@ Token names should only contain letters and digits separated by . characters.")} (mf/defc form {::mf/wrap-props false} - [{:keys [token token-type] :as _args}] - (let [tokens (mf/deref refs/workspace-ordered-token-sets-tokens) + [{:keys [token token-type]}] + (let [token (or token {:type token-type}) selected-set-tokens (mf/deref refs/workspace-selected-token-set-tokens) active-theme-tokens (mf/deref refs/workspace-active-theme-sets-tokens) resolved-tokens (sd/use-resolved-tokens active-theme-tokens {:names-map? true @@ -153,7 +157,7 @@ Token names should only contain letters and digits separated by . characters.")} (mf/deps (:name token)) #(wtt/token-name->path (:name token))) selected-set-tokens-tree (mf/use-memo - (mf/deps token-path tokens) + (mf/deps token-path selected-set-tokens) (fn [] (-> (wtt/token-names-tree selected-set-tokens) ;; Allow setting editing token to it's own path diff --git a/frontend/src/app/main/ui/workspace/tokens/modals.cljs b/frontend/src/app/main/ui/workspace/tokens/modals.cljs index 30a45c49f..5e4358d34 100644 --- a/frontend/src/app/main/ui/workspace/tokens/modals.cljs +++ b/frontend/src/app/main/ui/workspace/tokens/modals.cljs @@ -68,6 +68,12 @@ [properties] [:& token-update-create-modal properties]) +(mf/defc color-modal + {::mf/register modal/components + ::mf/register-as :tokens/color} + [properties] + [:& token-update-create-modal properties]) + (mf/defc stroke-width-modal {::mf/register modal/components ::mf/register-as :tokens/stroke-width} diff --git a/frontend/src/app/main/ui/workspace/tokens/sidebar.cljs b/frontend/src/app/main/ui/workspace/tokens/sidebar.cljs index 879ef97af..c333a9a68 100644 --- a/frontend/src/app/main/ui/workspace/tokens/sidebar.cljs +++ b/frontend/src/app/main/ui/workspace/tokens/sidebar.cljs @@ -77,6 +77,7 @@ (case type :border-radius i/corner-radius :numeric [:span {:class (stl/css :section-text-icon)} "123"] + :color i/drop-icon :boolean i/boolean-difference :opacity [:span {:class (stl/css :section-text-icon)} "%"] :rotation i/rotation diff --git a/frontend/src/app/main/ui/workspace/tokens/style_dictionary.cljs b/frontend/src/app/main/ui/workspace/tokens/style_dictionary.cljs index 62b068a32..919cfd738 100644 --- a/frontend/src/app/main/ui/workspace/tokens/style_dictionary.cljs +++ b/frontend/src/app/main/ui/workspace/tokens/style_dictionary.cljs @@ -52,6 +52,7 @@ (.buildAllPlatforms "json") (.catch js/console.error) (.then (fn [^js resp] + (js/console.log "resp" resp) (let [performance-end (js/performance.now) duration-ms (- performance-end performance-start) resolved-tokens (.-allTokens resp)] @@ -82,8 +83,11 @@ (let [identifier (if names-map? (.. cur -original -name) (uuid (.-uuid (.-id cur)))) - origin-token (get tokens identifier) - parsed-value (wtt/parse-token-value (.-value cur)) + {:keys [type] :as origin-token} (get tokens identifier) + value (.-value cur) + parsed-value (case type + :color (wtt/parse-token-color-value value) + (wtt/parse-token-value value)) resolved-token (if (not parsed-value) (assoc origin-token :errors [:style-dictionary/missing-reference]) (assoc origin-token @@ -132,6 +136,7 @@ (defn use-resolved-workspace-tokens [& {:as config}] (-> (mf/deref refs/workspace-selected-token-set-tokens) + (doto js/console.log) (use-resolved-tokens config))) (defn use-active-theme-sets-tokens [& {:as config}] diff --git a/frontend/src/app/main/ui/workspace/tokens/token.cljs b/frontend/src/app/main/ui/workspace/tokens/token.cljs index aba9ae9a0..32b85ab85 100644 --- a/frontend/src/app/main/ui/workspace/tokens/token.cljs +++ b/frontend/src/app/main/ui/workspace/tokens/token.cljs @@ -12,6 +12,15 @@ [token-id state] (get-in state [:workspace-data :tokens token-id])) +(def parseable-token-color-value-regexp + "Regexp that can be used to parse a hex value out of resolved token value. + This regexp also trims whitespace around the value." + #"^\s*#([A-Fa-f0-9]{3}|[A-Fa-f0-9]{6})\s*$") + +(defn parse-token-color-value [value] + (when-let [[_ hex] (re-find parseable-token-color-value-regexp value)] + {:value hex :unit :hex})) + (def parseable-token-value-regexp "Regexp that can be used to parse a number value out of resolved token value. This regexp also trims whitespace around the value." diff --git a/frontend/src/app/main/ui/workspace/tokens/token_types.cljs b/frontend/src/app/main/ui/workspace/tokens/token_types.cljs index 2faadab69..ce4c5cbf3 100644 --- a/frontend/src/app/main/ui/workspace/tokens/token_types.cljs +++ b/frontend/src/app/main/ui/workspace/tokens/token_types.cljs @@ -20,6 +20,14 @@ :modal {:key :tokens/border-radius :fields [{:label "Border Radius" :key :border-radius}]}} + + :color + {:title "Color" + :attributes ctt/color-keys + :on-update-shape wtch/update-color + :modal {:key :tokens/color + :fields [{:label "Color" :key :color}]}} + :stroke-width {:title "Stroke Width" :attributes ctt/stroke-width-keys diff --git a/frontend/src/app/main/ui/workspace/tokens/update.cljs b/frontend/src/app/main/ui/workspace/tokens/update.cljs index 2f64aa65b..5f0b581a9 100644 --- a/frontend/src/app/main/ui/workspace/tokens/update.cljs +++ b/frontend/src/app/main/ui/workspace/tokens/update.cljs @@ -19,6 +19,7 @@ (def attributes->shape-update {#{:rx :ry} (fn [v ids _] (wtch/update-shape-radius-all v ids)) #{:r1 :r2 :r3 :r4} wtch/update-shape-radius-single-corner + ctt/color-keys wtch/update-color ctt/stroke-width-keys wtch/update-stroke-width ctt/sizing-keys wtch/update-shape-dimensions ctt/opacity-keys wtch/update-opacity From 2b886c54e02054f6d917e1e767f7c1efc34194ec Mon Sep 17 00:00:00 2001 From: Florian Schroedl Date: Thu, 29 Aug 2024 12:52:18 +0200 Subject: [PATCH 02/19] Color ramp wip --- .../app/main/ui/workspace/tokens/form.cljs | 19 +++++++++++- .../app/main/ui/workspace/tokens/sidebar.cljs | 30 +++++++++++-------- .../app/main/ui/workspace/tokens/sidebar.scss | 1 + .../app/main/ui/workspace/tokens/token.cljs | 7 +++++ 4 files changed, 44 insertions(+), 13 deletions(-) diff --git a/frontend/src/app/main/ui/workspace/tokens/form.cljs b/frontend/src/app/main/ui/workspace/tokens/form.cljs index cc30768a6..2eb8a02e7 100644 --- a/frontend/src/app/main/ui/workspace/tokens/form.cljs +++ b/frontend/src/app/main/ui/workspace/tokens/form.cljs @@ -13,6 +13,8 @@ [app.main.data.tokens :as dt] [app.main.refs :as refs] [app.main.store :as st] + [app.main.ui.workspace.colorpicker :refer [colorpicker]] + [app.main.ui.workspace.colorpicker.ramp :refer [ramp-selector]] [app.main.ui.workspace.tokens.common :as tokens.common] [app.main.ui.workspace.tokens.style-dictionary :as sd] [app.main.ui.workspace.tokens.token :as wtt] @@ -145,10 +147,20 @@ Token names should only contain letters and digits separated by . characters.")} (defonce form-token-cache-atom (atom nil)) +(mf/defc ramp + [{:keys [color on-change]}] + (let [value (mf/use-state nil)] + (js/console.log "@value" @value) + [:& ramp-selector {:color @value + :on-start-drag js/console.log + :on-finish-drag js/console.log + :on-change #(reset! value (:hex %))}])) + (mf/defc form {::mf/wrap-props false} [{:keys [token token-type]}] (let [token (or token {:type token-type}) + color? (wtt/color-token? token) selected-set-tokens (mf/deref refs/workspace-selected-token-set-tokens) active-theme-tokens (mf/deref refs/workspace-active-theme-sets-tokens) resolved-tokens (sd/use-resolved-tokens active-theme-tokens {:names-map? true @@ -201,6 +213,7 @@ Token names should only contain letters and digits separated by . characters.")} (mf/deps on-update-value-debounced) (fn [e] (reset! value-ref (dom/get-target-val e)) + (js/console.log "e" e (dom/get-target-val e)) (on-update-value-debounced e))) value-error? (when (keyword? @token-resolve-result) (= (namespace @token-resolve-result) "error")) @@ -276,10 +289,14 @@ Token names should only contain letters and digits separated by . characters.")} [:p {:key error :class (stl/css :error)} error])] + ;; (when color? + ;; [:& ramp {:color @value-ref + ;; :on-change on-update-value}]) [:& tokens.common/labeled-input {:label "Value" :input-props {:default-value @value-ref :on-blur on-update-value - :on-change on-update-value}}] + :on-change on-update-value + :type (when color? "color")}}] [:div {:class (stl/css-case :resolved-value true :resolved-value-placeholder (nil? @token-resolve-result) :resolved-value-error value-error?)} diff --git a/frontend/src/app/main/ui/workspace/tokens/sidebar.cljs b/frontend/src/app/main/ui/workspace/tokens/sidebar.cljs index c333a9a68..9240d62c3 100644 --- a/frontend/src/app/main/ui/workspace/tokens/sidebar.cljs +++ b/frontend/src/app/main/ui/workspace/tokens/sidebar.cljs @@ -13,6 +13,7 @@ [app.main.data.tokens :as wdt] [app.main.refs :as refs] [app.main.store :as st] + [app.main.ui.components.color-bullet :refer [color-bullet]] [app.main.ui.components.title-bar :refer [title-bar]] [app.main.ui.hooks.resize :refer [use-resize-hook]] [app.main.ui.icons :as i] @@ -57,18 +58,23 @@ [{:keys [on-click token theme-token highlighted? on-context-menu] :as props}] (let [{:keys [name value resolved-value errors]} token errors? (and (seq errors) (seq (:errors theme-token)))] - [:button {:class (stl/css-case :token-pill true - :token-pill-highlighted highlighted? - :token-pill-invalid errors?) - :title (cond - errors? (sd/humanize-errors token) - :else (->> [(str "Token: " name) - (str "Original value: " value) - (str "Resolved value: " resolved-value)] - (str/join "\n"))) - :on-click on-click - :on-context-menu on-context-menu - :disabled errors?} + [:button + {:class (stl/css-case :token-pill true + :token-pill-highlighted highlighted? + :token-pill-invalid errors?) + :title (cond + errors? (sd/humanize-errors token) + :else (->> [(str "Token: " name) + (str "Original value: " value) + (str "Resolved value: " resolved-value)] + (str/join "\n"))) + :on-click on-click + :on-context-menu on-context-menu + :disabled errors?} + (js/console.log "resolved-value" resolved-value) + (when (wtt/color-token? token) + [:& color-bullet {:color (wtt/resolved-value-hex token) + :mini? true}]) name])) (mf/defc token-section-icon diff --git a/frontend/src/app/main/ui/workspace/tokens/sidebar.scss b/frontend/src/app/main/ui/workspace/tokens/sidebar.scss index 092a8bc86..ed2f1a9b7 100644 --- a/frontend/src/app/main/ui/workspace/tokens/sidebar.scss +++ b/frontend/src/app/main/ui/workspace/tokens/sidebar.scss @@ -72,6 +72,7 @@ .token-pill { @extend .button-secondary; + gap: $s-8; padding: $s-4 $s-8; border-radius: $br-6; font-size: $fs-14; diff --git a/frontend/src/app/main/ui/workspace/tokens/token.cljs b/frontend/src/app/main/ui/workspace/tokens/token.cljs index 32b85ab85..6ddd84f22 100644 --- a/frontend/src/app/main/ui/workspace/tokens/token.cljs +++ b/frontend/src/app/main/ui/workspace/tokens/token.cljs @@ -193,3 +193,10 @@ :else (-> (get path-target selector) (seq) (boolean))))) + +(defn color-token? [token] + (= (:type token) :color)) + +(defn resolved-value-hex [{:keys [resolved-value] :as token}] + (when (and resolved-value (color-token? token)) + (str "#" resolved-value))) From ac51309f81bb245c8bf919eb16270e13b33298b8 Mon Sep 17 00:00:00 2001 From: Florian Schroedl Date: Mon, 16 Sep 2024 15:59:04 +0200 Subject: [PATCH 03/19] Add placeholder color swatch --- .../src/app/main/ui/workspace/tokens/common.cljs | 2 +- .../src/app/main/ui/workspace/tokens/form.cljs | 14 +++++++++++--- .../src/app/main/ui/workspace/tokens/form.scss | 15 +++++++++++++++ 3 files changed, 27 insertions(+), 4 deletions(-) diff --git a/frontend/src/app/main/ui/workspace/tokens/common.cljs b/frontend/src/app/main/ui/workspace/tokens/common.cljs index 7f1c78779..ea0b8bc65 100644 --- a/frontend/src/app/main/ui/workspace/tokens/common.cljs +++ b/frontend/src/app/main/ui/workspace/tokens/common.cljs @@ -125,7 +125,7 @@ (mf/defc labeled-input {::mf/wrap-props false} - [{:keys [label input-props auto-complete? error? icon render-right]}] + [{:keys [label input-props auto-complete? error? render-right]}] (let [input-props (cond-> input-props :always camel-keys ;; Disable auto-complete on form fields for proprietary password managers diff --git a/frontend/src/app/main/ui/workspace/tokens/form.cljs b/frontend/src/app/main/ui/workspace/tokens/form.cljs index 2eb8a02e7..aa819801c 100644 --- a/frontend/src/app/main/ui/workspace/tokens/form.cljs +++ b/frontend/src/app/main/ui/workspace/tokens/form.cljs @@ -13,6 +13,7 @@ [app.main.data.tokens :as dt] [app.main.refs :as refs] [app.main.store :as st] + [app.main.ui.components.color-bullet :refer [color-bullet]] [app.main.ui.workspace.colorpicker :refer [colorpicker]] [app.main.ui.workspace.colorpicker.ramp :refer [ramp-selector]] [app.main.ui.workspace.tokens.common :as tokens.common] @@ -199,6 +200,7 @@ Token names should only contain letters and digits separated by . characters.")} (valid-name? @name-ref)) ;; Value + color (mf/use-state (when color? (:value token))) value-ref (mf/use-var (:value token)) token-resolve-result (mf/use-state (get-in resolved-tokens [(wtt/token-identifier token) :resolved-value])) set-resolve-value (mf/use-callback @@ -207,13 +209,13 @@ Token names should only contain letters and digits separated by . characters.")} (= token-or-err :error/token-direct-self-reference) token-or-err (= token-or-err :error/token-missing-reference) token-or-err (:resolved-value token-or-err) (:resolved-value token-or-err))] + (when color? (reset! color v)) (reset! token-resolve-result v)))) on-update-value-debounced (use-debonced-resolve-callback name-ref token active-theme-tokens set-resolve-value) on-update-value (mf/use-callback (mf/deps on-update-value-debounced) (fn [e] (reset! value-ref (dom/get-target-val e)) - (js/console.log "e" e (dom/get-target-val e)) (on-update-value-debounced e))) value-error? (when (keyword? @token-resolve-result) (= (namespace @token-resolve-result) "error")) @@ -295,8 +297,14 @@ Token names should only contain letters and digits separated by . characters.")} [:& tokens.common/labeled-input {:label "Value" :input-props {:default-value @value-ref :on-blur on-update-value - :on-change on-update-value - :type (when color? "color")}}] + :on-change on-update-value} + :render-right (when color? + (mf/fnc [] + [:div {:class (stl/css :color-bullet)} + (if @color + [:& color-bullet {:color @color + :mini? true}] + [:div {:class (stl/css :color-bullet-placeholder)}])]))}] [:div {:class (stl/css-case :resolved-value true :resolved-value-placeholder (nil? @token-resolve-result) :resolved-value-error value-error?)} diff --git a/frontend/src/app/main/ui/workspace/tokens/form.scss b/frontend/src/app/main/ui/workspace/tokens/form.scss index cb67c9001..08df786fc 100644 --- a/frontend/src/app/main/ui/workspace/tokens/form.scss +++ b/frontend/src/app/main/ui/workspace/tokens/form.scss @@ -48,3 +48,18 @@ .resolved-value-error { color: var(--status-color-error-500); } + +.color-bullet { + margin-right: $s-8; +} + +.color-bullet-placeholder { + width: var(--bullet-size, $s-16); + height: var(--bullet-size, $s-16); + min-width: var(--bullet-size, $s-16); + min-height: var(--bullet-size, $s-16); + margin-top: 0; + background-color: color-mix(in hsl, var(--color-foreground-secondary) 30%, transparent); + border-radius: $br-4; + cursor: pointer; +} From 3c4e0e244785d1374d2925f3559712af61e986c1 Mon Sep 17 00:00:00 2001 From: Florian Schroedl Date: Mon, 16 Sep 2024 16:57:01 +0200 Subject: [PATCH 04/19] Add color ramp --- .../main/ui/workspace/colorpicker/ramp.cljs | 1 + .../app/main/ui/workspace/tokens/form.cljs | 49 +++++++++++++------ 2 files changed, 34 insertions(+), 16 deletions(-) diff --git a/frontend/src/app/main/ui/workspace/colorpicker/ramp.cljs b/frontend/src/app/main/ui/workspace/colorpicker/ramp.cljs index 970525d3c..cc70d887c 100644 --- a/frontend/src/app/main/ui/workspace/colorpicker/ramp.cljs +++ b/frontend/src/app/main/ui/workspace/colorpicker/ramp.cljs @@ -52,6 +52,7 @@ (mf/defc ramp-selector [{:keys [color disable-opacity on-change on-start-drag on-finish-drag]}] + (js/console.log "color" color) (let [{hex :hex hue :h saturation :s value :v alpha :alpha} color diff --git a/frontend/src/app/main/ui/workspace/tokens/form.cljs b/frontend/src/app/main/ui/workspace/tokens/form.cljs index aa819801c..025299a8e 100644 --- a/frontend/src/app/main/ui/workspace/tokens/form.cljs +++ b/frontend/src/app/main/ui/workspace/tokens/form.cljs @@ -8,13 +8,13 @@ (:require-macros [app.main.style :as stl]) (:require ["lodash.debounce" :as debounce] + [app.common.colors :as cc] [app.common.data :as d] [app.main.data.modal :as modal] [app.main.data.tokens :as dt] [app.main.refs :as refs] [app.main.store :as st] [app.main.ui.components.color-bullet :refer [color-bullet]] - [app.main.ui.workspace.colorpicker :refer [colorpicker]] [app.main.ui.workspace.colorpicker.ramp :refer [ramp-selector]] [app.main.ui.workspace.tokens.common :as tokens.common] [app.main.ui.workspace.tokens.style-dictionary :as sd] @@ -127,16 +127,15 @@ Token names should only contain letters and digits separated by . characters.")} debounced-resolver-callback (mf/use-callback (mf/deps token callback tokens) - (fn [event] - (let [input (dom/get-target-val event) - timeout-id (js/Symbol) + (fn [value] + (let [timeout-id (js/Symbol) ;; Dont execute callback when the timout-id-ref is outdated because this function got called again timeout-outdated-cb? #(not= (mf/ref-val timeout-id-ref) timeout-id)] (mf/set-ref-val! timeout-id-ref timeout-id) (js/setTimeout (fn [] (when (not (timeout-outdated-cb?)) - (-> (validate-token-value+ {:input input + (-> (validate-token-value+ {:input value :name-value @name-ref :token token :tokens tokens}) @@ -150,12 +149,22 @@ Token names should only contain letters and digits separated by . characters.")} (mf/defc ramp [{:keys [color on-change]}] - (let [value (mf/use-state nil)] - (js/console.log "@value" @value) + (js/console.log "color" color) + (let [dragging? (mf/use-state) + [r g b] (cc/hex->rgb color) + [h s v] (cc/hex->hsv color) + value (mf/use-state {:hex color + :r r :g g :b b + :h h :s s :v v}) + on-change' (fn [color] + (swap! value merge color) + (when-not (and @dragging? (:hex color)) + (on-change (:hex color))))] [:& ramp-selector {:color @value - :on-start-drag js/console.log - :on-finish-drag js/console.log - :on-change #(reset! value (:hex %))}])) + :disable-opacity true + :on-start-drag #(reset! dragging? true) + :on-finish-drag #(reset! dragging? false) + :on-change on-change'}])) (mf/defc form {::mf/wrap-props false} @@ -201,6 +210,7 @@ Token names should only contain letters and digits separated by . characters.")} ;; Value color (mf/use-state (when color? (:value token))) + color-ramp-open? (mf/use-state false) value-ref (mf/use-var (:value token)) token-resolve-result (mf/use-state (get-in resolved-tokens [(wtt/token-identifier token) :resolved-value])) set-resolve-value (mf/use-callback @@ -215,8 +225,14 @@ Token names should only contain letters and digits separated by . characters.")} on-update-value (mf/use-callback (mf/deps on-update-value-debounced) (fn [e] - (reset! value-ref (dom/get-target-val e)) - (on-update-value-debounced e))) + (let [value (dom/get-target-val e)] + (reset! value-ref value) + (on-update-value-debounced value)))) + on-update-color (mf/use-callback + (mf/deps on-update-value-debounced) + (fn [hex-value] + (reset! value-ref hex-value) + (on-update-value-debounced hex-value))) value-error? (when (keyword? @token-resolve-result) (= (namespace @token-resolve-result) "error")) valid-value-field? (and @@ -291,20 +307,21 @@ Token names should only contain letters and digits separated by . characters.")} [:p {:key error :class (stl/css :error)} error])] - ;; (when color? - ;; [:& ramp {:color @value-ref - ;; :on-change on-update-value}]) [:& tokens.common/labeled-input {:label "Value" :input-props {:default-value @value-ref :on-blur on-update-value :on-change on-update-value} :render-right (when color? (mf/fnc [] - [:div {:class (stl/css :color-bullet)} + [:div {:class (stl/css :color-bullet) + :on-click #(swap! color-ramp-open? not)} (if @color [:& color-bullet {:color @color :mini? true}] [:div {:class (stl/css :color-bullet-placeholder)}])]))}] + (when @color-ramp-open? + [:& ramp {:color (or @token-resolve-result (:value token)) + :on-change on-update-color}]) [:div {:class (stl/css-case :resolved-value true :resolved-value-placeholder (nil? @token-resolve-result) :resolved-value-error value-error?)} From 49ff0df7f6e8e3c41bf92c2a392d21f81c2b945d Mon Sep 17 00:00:00 2001 From: Florian Schroedl Date: Tue, 17 Sep 2024 16:35:08 +0200 Subject: [PATCH 05/19] Add tinycolor bindings --- frontend/package.json | 1 + .../main/ui/workspace/tokens/tinycolor.cljs | 26 +++++++++++++++++++ frontend/yarn.lock | 1 + 3 files changed, 28 insertions(+) create mode 100644 frontend/src/app/main/ui/workspace/tokens/tinycolor.cljs diff --git a/frontend/package.json b/frontend/package.json index c7d620fc8..047329918 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -116,6 +116,7 @@ "source-map-support": "^0.5.21", "style-dictionary": "patch:style-dictionary@npm%3A4.0.0-prerelease.36#~/.yarn/patches/style-dictionary-npm-4.0.0-prerelease.36-55c0fc33bd.patch", "tdigest": "^0.1.2", + "tinycolor2": "npm:^1.6.0", "ua-parser-js": "^1.0.38", "xregexp": "^5.1.1" } diff --git a/frontend/src/app/main/ui/workspace/tokens/tinycolor.cljs b/frontend/src/app/main/ui/workspace/tokens/tinycolor.cljs new file mode 100644 index 000000000..99fd64f84 --- /dev/null +++ b/frontend/src/app/main/ui/workspace/tokens/tinycolor.cljs @@ -0,0 +1,26 @@ +(ns app.main.ui.workspace.tokens.tinycolor + "Bindings for tinycolor2 which supports a wide range of css compatible colors. + + Used by StyleDictionary, so we might as well use it directly." + (:require + ["tinycolor2" :as tinycolor])) + +(defn tinycolor? [x] + (and (instance? tinycolor x) (.isValid x))) + +(defn valid-color [color-str] + (let [tc (tinycolor color-str)] + (when (.isValid tc) tc))) + +(defn ->hex [tc] + (assert (tinycolor? tc)) + (.toHex tc)) + +(defn color-format [tc] + (assert (tinycolor? tc)) + (.getFormat tc)) + +(comment + (some-> (valid-color "red") ->hex) + (some-> (valid-color "red") color-format) + nil) diff --git a/frontend/yarn.lock b/frontend/yarn.lock index ebde9b8cf..b13ad3a1a 100644 --- a/frontend/yarn.lock +++ b/frontend/yarn.lock @@ -6966,6 +6966,7 @@ __metadata: style-dictionary: "patch:style-dictionary@npm%3A4.0.0-prerelease.36#~/.yarn/patches/style-dictionary-npm-4.0.0-prerelease.36-55c0fc33bd.patch" svg-sprite: "npm:^2.0.4" tdigest: "npm:^0.1.2" + tinycolor2: "npm:^1.6.0" typescript: "npm:^5.4.5" ua-parser-js: "npm:^1.0.38" vite: "npm:^5.1.4" From 308fff05c3d93a3a38e5eec2b3a0f6539cd12c95 Mon Sep 17 00:00:00 2001 From: Florian Schroedl Date: Wed, 18 Sep 2024 10:19:59 +0200 Subject: [PATCH 06/19] Dont show name error when editing new token and not touching name field --- frontend/src/app/main/ui/workspace/tokens/form.cljs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/frontend/src/app/main/ui/workspace/tokens/form.cljs b/frontend/src/app/main/ui/workspace/tokens/form.cljs index 025299a8e..faaf664af 100644 --- a/frontend/src/app/main/ui/workspace/tokens/form.cljs +++ b/frontend/src/app/main/ui/workspace/tokens/form.cljs @@ -169,7 +169,8 @@ Token names should only contain letters and digits separated by . characters.")} (mf/defc form {::mf/wrap-props false} [{:keys [token token-type]}] - (let [token (or token {:type token-type}) + (let [validate-name? (mf/use-state (not (:id token))) + token (or token {:type token-type}) color? (wtt/color-token? token) selected-set-tokens (mf/deref refs/workspace-selected-token-set-tokens) active-theme-tokens (mf/deref refs/workspace-active-theme-sets-tokens) @@ -198,7 +199,10 @@ Token names should only contain letters and digits separated by . characters.")} (debounce (fn [e] (let [value (dom/get-target-val e) errors (validate-name value)] - (reset! name-errors errors))))) + ;; Prevent showing error when just going to another field on a new token + (when-not (and validate-name? (str/empty? value)) + (reset! validate-name? false) + (reset! name-errors errors)))))) on-update-name (mf/use-callback (mf/deps on-update-name-debounced) (fn [e] From 3a21643158bbc83ac7542c75e6c2281f1a745bfc Mon Sep 17 00:00:00 2001 From: Florian Schroedl Date: Wed, 18 Sep 2024 10:38:16 +0200 Subject: [PATCH 07/19] Add shared error handling --- .../app/main/ui/workspace/tokens/errors.cljs | 22 ++++ .../app/main/ui/workspace/tokens/form.cljs | 119 ++++++++++-------- .../ui/workspace/tokens/style_dictionary.cljs | 34 ++--- 3 files changed, 106 insertions(+), 69 deletions(-) create mode 100644 frontend/src/app/main/ui/workspace/tokens/errors.cljs diff --git a/frontend/src/app/main/ui/workspace/tokens/errors.cljs b/frontend/src/app/main/ui/workspace/tokens/errors.cljs new file mode 100644 index 000000000..471d9c59f --- /dev/null +++ b/frontend/src/app/main/ui/workspace/tokens/errors.cljs @@ -0,0 +1,22 @@ +(ns app.main.ui.workspace.tokens.errors) + +(def error-codes + {:error.token/direct-self-reference + {:error/fn #(str "Token has self reference in name: " %)} + :error.token/invalid-color + {:error/fn #(str "Invalid color value: " %)} + :error.style-dictionary/missing-reference + {:error/fn #(str "Could not resolve reference token with name: " %)} + :error.style-dictionary/invalid-token-value + {:error/message "Invalid token value"} + :error/unknown + {:error/message "Unknown error"}}) + +(defn humanize-errors [v errors] + (->> errors + (map (fn [err] + (let [err' (get error-codes err err)] + (cond + (:error/fn err') ((:error/fn err') v) + (:error/message err') (:error/message err') + :else err')))))) diff --git a/frontend/src/app/main/ui/workspace/tokens/form.cljs b/frontend/src/app/main/ui/workspace/tokens/form.cljs index faaf664af..efbca9d7a 100644 --- a/frontend/src/app/main/ui/workspace/tokens/form.cljs +++ b/frontend/src/app/main/ui/workspace/tokens/form.cljs @@ -7,6 +7,7 @@ (ns app.main.ui.workspace.tokens.form (:require-macros [app.main.style :as stl]) (:require + [app.main.ui.workspace.tokens.errors :as wte] ["lodash.debounce" :as debounce] [app.common.colors :as cc] [app.common.data :as d] @@ -25,7 +26,8 @@ [malli.core :as m] [malli.error :as me] [promesa.core :as p] - [rumext.v2 :as mf])) + [rumext.v2 :as mf] + [app.main.ui.workspace.tokens.tinycolor :as tinycolor])) ;; Schemas --------------------------------------------------------------------- @@ -87,36 +89,39 @@ Token names should only contain letters and digits separated by . characters.")} ;; Component ------------------------------------------------------------------- +(defn token-self-reference? + [token-name input] + (let [token-references (wtt/find-token-references input) + self-reference? (get token-references token-name)] + self-reference?)) + (defn validate-token-value+ "Validates token value by resolving the value `input` using `StyleDictionary`. Returns a promise of either resolved tokens or rejects with an error state." [{:keys [input name-value token tokens]}] - (let [empty-input? (empty? (str/trim input)) - ;; Check if the given value contains a reference that is the current token-name - ;; When creating a new token we dont have a token name yet, - ;; so we use a temporary token name that hopefully doesn't clash with any of the users token names. - token-name (if (str/empty? name-value) "__TOKEN_STUDIO_SYSTEM.TEMP" name-value) - token-references (wtt/find-token-references input) - direct-self-reference? (get token-references token-name)] + (let [ ;; When creating a new token we dont have a token name yet, + ;; so we use a temporary token name that hopefully doesn't clash with any of the users token names + token-name (if (str/empty? name-value) "__TOKEN_STUDIO_SYSTEM.TEMP" name-value)] (cond - empty-input? (p/rejected nil) - direct-self-reference? (p/rejected :error/token-direct-self-reference) - :else (let [token-id (or (:id token) (random-uuid)) - new-tokens (update tokens token-name merge {:id token-id - :value input - :name token-name - :type (:type token)})] - (-> (sd/resolve-tokens+ new-tokens {:names-map? true - :debug? true}) - (p/then - (fn [resolved-tokens] - (js/console.log "resolved-tokens" resolved-tokens) - (let [{:keys [errors resolved-value] :as resolved-token} (get resolved-tokens token-name)] - (cond - resolved-value (p/resolved resolved-token) - (sd/missing-reference-error? errors) (p/rejected :error/token-missing-reference) - :else (p/rejected :error/unknown-error))))) - (p/catch js/console.log)))))) + (empty? (str/trim input)) + (p/rejected {:errors #{:error/empty-input}}) + + (token-self-reference? token-name input) + (p/rejected {:errors #{:error.token/direct-self-reference}}) + + :else + (let [token-id (or (:id token) (random-uuid)) + new-tokens (update tokens token-name merge {:id token-id + :value input + :name token-name + :type (:type token)})] + (-> (sd/resolve-tokens+ new-tokens {:names-map? true}) + (p/then + (fn [resolved-tokens] + (let [{:keys [errors resolved-value] :as resolved-token} (get resolved-tokens token-name)] + (cond + resolved-value (p/resolved resolved-token) + :else (p/rejected {:errors (or errors #{:error/unknown-error})})))))))))) (defn use-debonced-resolve-callback "Resolves a token values using `StyleDictionary`. @@ -139,9 +144,10 @@ Token names should only contain letters and digits separated by . characters.")} :name-value @name-ref :token token :tokens tokens}) - (p/finally (fn [x err] - (when-not (timeout-outdated-cb?) - (callback (or err x)))))))) + (p/finally + (fn [x err] + (when-not (timeout-outdated-cb?) + (callback (or err x)))))))) timeout))))] debounced-resolver-callback)) @@ -149,7 +155,6 @@ Token names should only contain letters and digits separated by . characters.")} (mf/defc ramp [{:keys [color on-change]}] - (js/console.log "color" color) (let [dragging? (mf/use-state) [r g b] (cc/hex->rgb color) [h s v] (cc/hex->hsv color) @@ -166,6 +171,20 @@ Token names should only contain letters and digits separated by . characters.")} :on-finish-drag #(reset! dragging? false) :on-change on-change'}])) +(mf/defc token-value-or-errors + [{:keys [result-or-errors]}] + (let [{:keys [errors]} result-or-errors + empty-message? (or (nil? result-or-errors) + (= errors #{:error/empty-input}))] + [:div {:class (stl/css-case :resolved-value true + :resolved-value-placeholder empty-message? + :resolved-value-error (seq errors))} + (cond + empty-message? "Enter token value" + errors (->> (wte/humanize-errors (:value result-or-errors) errors) + (str/join "\n")) + :else [:p result-or-errors])])) + (mf/defc form {::mf/wrap-props false} [{:keys [token token-type]}] @@ -219,11 +238,11 @@ Token names should only contain letters and digits separated by . characters.")} token-resolve-result (mf/use-state (get-in resolved-tokens [(wtt/token-identifier token) :resolved-value])) set-resolve-value (mf/use-callback (fn [token-or-err] - (let [v (cond - (= token-or-err :error/token-direct-self-reference) token-or-err - (= token-or-err :error/token-missing-reference) token-or-err - (:resolved-value token-or-err) (:resolved-value token-or-err))] - (when color? (reset! color v)) + (let [error? (:errors token-or-err) + v (if error? + token-or-err + (:resolved-value token-or-err))] + (when color? (reset! color (if error? nil v))) (reset! token-resolve-result v)))) on-update-value-debounced (use-debonced-resolve-callback name-ref token active-theme-tokens set-resolve-value) on-update-value (mf/use-callback @@ -237,8 +256,7 @@ Token names should only contain letters and digits separated by . characters.")} (fn [hex-value] (reset! value-ref hex-value) (on-update-value-debounced hex-value))) - value-error? (when (keyword? @token-resolve-result) - (= (namespace @token-resolve-result) "error")) + value-error? (seq (:errors @token-resolve-result)) valid-value-field? (and (not value-error?) (valid-value? @token-resolve-result)) @@ -317,24 +335,19 @@ Token names should only contain letters and digits separated by . characters.")} :on-change on-update-value} :render-right (when color? (mf/fnc [] - [:div {:class (stl/css :color-bullet) - :on-click #(swap! color-ramp-open? not)} - (if @color - [:& color-bullet {:color @color - :mini? true}] - [:div {:class (stl/css :color-bullet-placeholder)}])]))}] + [:div {:class (stl/css :color-bullet) + :on-click #(swap! color-ramp-open? not)} + (if-let [hex (some-> @color tinycolor/valid-color tinycolor/->hex)] + [:& color-bullet {:color hex + :mini? true}] + [:div {:class (stl/css :color-bullet-placeholder)}])]))}] (when @color-ramp-open? - [:& ramp {:color (or @token-resolve-result (:value token)) + [:& ramp {:color (some-> (or @token-resolve-result (:value token)) + (tinycolor/valid-color) + (tinycolor/->hex)) :on-change on-update-color}]) - [:div {:class (stl/css-case :resolved-value true - :resolved-value-placeholder (nil? @token-resolve-result) - :resolved-value-error value-error?)} - (case @token-resolve-result - :error/token-direct-self-reference "Token has self reference" - :error/token-missing-reference "Token has missing reference" - :error/unknown-error "" - nil "Enter token value" - [:p @token-resolve-result])] + [:& token-value-or-errors {:result-or-errors @token-resolve-result}] + [:div [:& tokens.common/labeled-input {:label "Description" :input-props {:default-value @description-ref diff --git a/frontend/src/app/main/ui/workspace/tokens/style_dictionary.cljs b/frontend/src/app/main/ui/workspace/tokens/style_dictionary.cljs index 919cfd738..8c6a126f4 100644 --- a/frontend/src/app/main/ui/workspace/tokens/style_dictionary.cljs +++ b/frontend/src/app/main/ui/workspace/tokens/style_dictionary.cljs @@ -2,8 +2,8 @@ (:require ["@tokens-studio/sd-transforms" :as sd-transforms] ["style-dictionary$default" :as sd] - [app.common.data :refer [ordered-map]] [app.main.refs :as refs] + [app.main.ui.workspace.tokens.tinycolor :as tinycolor] [app.main.ui.workspace.tokens.token :as wtt] [cuerdas.core :as str] [promesa.core :as p] @@ -61,19 +61,15 @@ (js/console.log "Resolved tokens" resolved-tokens)) resolved-tokens)))))) + (defn humanize-errors [{:keys [errors value] :as _token}] (->> (map (fn [err] (case err - :style-dictionary/missing-reference (str "Could not resolve reference token with the name: " value) + :error.style-dictionary/missing-reference (str "Could not resolve reference token with the name: " value) nil)) errors) (str/join "\n"))) -(defn missing-reference-error? - [errors] - (and (set? errors) - (get errors :style-dictionary/missing-reference))) - (defn resolve-tokens+ [tokens & {:keys [names-map? debug?] :as config}] (p/let [sd-tokens (-> (wtt/token-names-tree tokens) @@ -85,15 +81,21 @@ (uuid (.-uuid (.-id cur)))) {:keys [type] :as origin-token} (get tokens identifier) value (.-value cur) - parsed-value (case type - :color (wtt/parse-token-color-value value) - (wtt/parse-token-value value)) - resolved-token (if (not parsed-value) - (assoc origin-token :errors [:style-dictionary/missing-reference]) - (assoc origin-token - :resolved-value (:value parsed-value) - :resolved-unit (:unit parsed-value)))] - (assoc acc (wtt/token-identifier resolved-token) resolved-token))) + token-or-err (case type + :color (if-let [tc (tinycolor/valid-color value)] + {:value value :unit (tinycolor/color-format tc)} + {:errors #{:error.token/invalid-color}}) + (or (wtt/parse-token-value value) + (if-let [references (seq (wtt/find-token-references value))] + {:errors #{:error.style-dictionary/missing-reference} + :references references} + {:errors #{:error.style-dictionary/invalid-token-value}}))) + output-token (if (:errors token-or-err) + (merge origin-token token-or-err) + (assoc origin-token + :resolved-value (:value token-or-err) + :unit (:unit token-or-err)))] + (assoc acc (wtt/token-identifier output-token) output-token))) {} sd-tokens)] (when debug? (js/console.log "Resolved tokens" resolved-tokens)) From 77141887a8a742848301d59cb9c7b6371dc39444 Mon Sep 17 00:00:00 2001 From: Florian Schroedl Date: Wed, 18 Sep 2024 10:57:05 +0200 Subject: [PATCH 08/19] Pass in value with error --- .../app/main/ui/workspace/tokens/errors.cljs | 53 +++++++++++++------ .../app/main/ui/workspace/tokens/form.cljs | 10 ++-- .../ui/workspace/tokens/style_dictionary.cljs | 12 +++-- 3 files changed, 49 insertions(+), 26 deletions(-) diff --git a/frontend/src/app/main/ui/workspace/tokens/errors.cljs b/frontend/src/app/main/ui/workspace/tokens/errors.cljs index 471d9c59f..74ec8c335 100644 --- a/frontend/src/app/main/ui/workspace/tokens/errors.cljs +++ b/frontend/src/app/main/ui/workspace/tokens/errors.cljs @@ -1,22 +1,43 @@ -(ns app.main.ui.workspace.tokens.errors) +(ns app.main.ui.workspace.tokens.errors + (:require + [cuerdas.core :as str])) (def error-codes {:error.token/direct-self-reference - {:error/fn #(str "Token has self reference in name: " %)} - :error.token/invalid-color - {:error/fn #(str "Invalid color value: " %)} - :error.style-dictionary/missing-reference - {:error/fn #(str "Could not resolve reference token with name: " %)} - :error.style-dictionary/invalid-token-value - {:error/message "Invalid token value"} - :error/unknown - {:error/message "Unknown error"}}) + {:error/code :error.token/direct-self-reference + :error/message "Token has self reference"} -(defn humanize-errors [v errors] + :error.token/invalid-color + {:error/code :error.token/invalid-color + :error/fn #(str "Invalid color value: " %)} + + :error.style-dictionary/missing-reference + {:error/code :error.style-dictionary/missing-reference + :error/fn #(str "Missing token references: " (str/join " " %))} + + :error.style-dictionary/invalid-token-value + {:error/code :error.style-dictionary/invalid-token-value + :error/fn #(str "Invalid token value: " %)} + + :error/unknown + {:error/code :error/unknown + :error/message "Unknown error"}}) + +(defn get-error-code [error-key] + (get error-codes error-key (:error/unknown error-codes))) + +(defn error-with-value [error-key error-value] + (-> (get-error-code error-key) + (assoc :error/value error-value))) + +(defn has-error-code? [error-key errors] + (some #(= (:error/code %) error-key) errors)) + +(defn humanize-errors [errors] (->> errors (map (fn [err] - (let [err' (get error-codes err err)] - (cond - (:error/fn err') ((:error/fn err') v) - (:error/message err') (:error/message err') - :else err')))))) + (js/console.log "err" err) + (cond + (:error/fn err) ((:error/fn err) (:error/value err)) + (:error/message err) (:error/message err) + :else err))))) diff --git a/frontend/src/app/main/ui/workspace/tokens/form.cljs b/frontend/src/app/main/ui/workspace/tokens/form.cljs index efbca9d7a..83d80dfc1 100644 --- a/frontend/src/app/main/ui/workspace/tokens/form.cljs +++ b/frontend/src/app/main/ui/workspace/tokens/form.cljs @@ -104,10 +104,10 @@ Token names should only contain letters and digits separated by . characters.")} token-name (if (str/empty? name-value) "__TOKEN_STUDIO_SYSTEM.TEMP" name-value)] (cond (empty? (str/trim input)) - (p/rejected {:errors #{:error/empty-input}}) + (p/rejected {:errors [{:error/code :error/empty-input}]}) (token-self-reference? token-name input) - (p/rejected {:errors #{:error.token/direct-self-reference}}) + (p/rejected {:errors [(wte/get-error-code :error.token/direct-self-reference)]}) :else (let [token-id (or (:id token) (random-uuid)) @@ -121,7 +121,7 @@ Token names should only contain letters and digits separated by . characters.")} (let [{:keys [errors resolved-value] :as resolved-token} (get resolved-tokens token-name)] (cond resolved-value (p/resolved resolved-token) - :else (p/rejected {:errors (or errors #{:error/unknown-error})})))))))))) + :else (p/rejected {:errors (or errors (wte/get-error-code :error/unknown-error))})))))))))) (defn use-debonced-resolve-callback "Resolves a token values using `StyleDictionary`. @@ -175,13 +175,13 @@ Token names should only contain letters and digits separated by . characters.")} [{:keys [result-or-errors]}] (let [{:keys [errors]} result-or-errors empty-message? (or (nil? result-or-errors) - (= errors #{:error/empty-input}))] + (wte/has-error-code? :error/empty-input errors))] [:div {:class (stl/css-case :resolved-value true :resolved-value-placeholder empty-message? :resolved-value-error (seq errors))} (cond empty-message? "Enter token value" - errors (->> (wte/humanize-errors (:value result-or-errors) errors) + errors (->> (wte/humanize-errors errors) (str/join "\n")) :else [:p result-or-errors])])) diff --git a/frontend/src/app/main/ui/workspace/tokens/style_dictionary.cljs b/frontend/src/app/main/ui/workspace/tokens/style_dictionary.cljs index 8c6a126f4..b35d98c33 100644 --- a/frontend/src/app/main/ui/workspace/tokens/style_dictionary.cljs +++ b/frontend/src/app/main/ui/workspace/tokens/style_dictionary.cljs @@ -7,7 +7,8 @@ [app.main.ui.workspace.tokens.token :as wtt] [cuerdas.core :as str] [promesa.core :as p] - [rumext.v2 :as mf])) + [rumext.v2 :as mf] + [app.main.ui.workspace.tokens.errors :as wte])) (def StyleDictionary "Initiates the global StyleDictionary instance with transforms @@ -84,12 +85,13 @@ token-or-err (case type :color (if-let [tc (tinycolor/valid-color value)] {:value value :unit (tinycolor/color-format tc)} - {:errors #{:error.token/invalid-color}}) + {:errors [(wte/error-with-value :error.token/invalid-color value)]}) (or (wtt/parse-token-value value) - (if-let [references (seq (wtt/find-token-references value))] - {:errors #{:error.style-dictionary/missing-reference} + (if-let [references (-> (wtt/find-token-references value) + (seq))] + {:errors [(wte/error-with-value :error.style-dictionary/missing-reference references)] :references references} - {:errors #{:error.style-dictionary/invalid-token-value}}))) + {:errors [(wte/error-with-value :error.style-dictionary/invalid-token-value value)]}))) output-token (if (:errors token-or-err) (merge origin-token token-or-err) (assoc origin-token From 3bd2278dec0064cac9df6a3d47a2ca81bbe3d23b Mon Sep 17 00:00:00 2001 From: Florian Schroedl Date: Wed, 18 Sep 2024 11:15:11 +0200 Subject: [PATCH 09/19] Use penpot logging system instead of custom debug flag --- .../ui/workspace/tokens/style_dictionary.cljs | 41 +++++++++---------- 1 file changed, 19 insertions(+), 22 deletions(-) diff --git a/frontend/src/app/main/ui/workspace/tokens/style_dictionary.cljs b/frontend/src/app/main/ui/workspace/tokens/style_dictionary.cljs index b35d98c33..72e133730 100644 --- a/frontend/src/app/main/ui/workspace/tokens/style_dictionary.cljs +++ b/frontend/src/app/main/ui/workspace/tokens/style_dictionary.cljs @@ -2,13 +2,16 @@ (:require ["@tokens-studio/sd-transforms" :as sd-transforms] ["style-dictionary$default" :as sd] + [app.common.logging :as l] [app.main.refs :as refs] + [app.main.ui.workspace.tokens.errors :as wte] [app.main.ui.workspace.tokens.tinycolor :as tinycolor] [app.main.ui.workspace.tokens.token :as wtt] [cuerdas.core :as str] [promesa.core :as p] - [rumext.v2 :as mf] - [app.main.ui.workspace.tokens.errors :as wte])) + [rumext.v2 :as mf])) + +(l/set-level! "app.main.ui.workspace.tokens.style-dictionary" :warn) (def StyleDictionary "Initiates the global StyleDictionary instance with transforms @@ -25,7 +28,7 @@ (defn tokens->style-dictionary+ "Resolves references and math expressions using StyleDictionary. Returns a promise with the resolved dictionary." - [tokens {:keys [debug?]}] + [tokens] (let [data (cond-> {:tokens tokens :platforms {:json {:transformGroup "tokens-studio" :files [{:format "custom/json" @@ -34,35 +37,31 @@ :warnings "silent" :errors {:brokenReferences "console"}} :preprocessors ["tokens-studio"]} - debug? (update :log merge {:verbosity "verbose" - :warnings "warn"})) + (l/enabled? "app.main.ui.workspace.tokens.style-dictionary" :debug) + (update :log merge {:verbosity "verbose" + :warnings "warn"})) js-data (clj->js data)] - (when debug? - (js/console.log "Input Data" js-data)) + (l/debug :hint "Input Data" :js/data js-data) (sd. js-data))) (defn resolve-sd-tokens+ "Resolves references and math expressions using StyleDictionary. Returns a promise with the resolved dictionary." - [tokens & {:keys [debug?] :as config}] + [tokens] (let [performance-start (js/performance.now) - sd (tokens->style-dictionary+ tokens config)] - (when debug? - (js/console.log "StyleDictionary" sd)) + sd (tokens->style-dictionary+ tokens)] + (l/debug :hint "StyleDictionary" :js/style-dictionary sd) (-> sd (.buildAllPlatforms "json") - (.catch js/console.error) + (.catch #(l/error :hint "Styledictionary build error" :js/error %)) (.then (fn [^js resp] - (js/console.log "resp" resp) (let [performance-end (js/performance.now) duration-ms (- performance-end performance-start) resolved-tokens (.-allTokens resp)] - (when debug? - (js/console.log "Time elapsed" duration-ms "ms") - (js/console.log "Resolved tokens" resolved-tokens)) + (l/debug :hint (str "Time elapsed" duration-ms "ms") :duration duration-ms) + (l/debug :hint "Resolved tokens" :js/tokens resolved-tokens) resolved-tokens)))))) - (defn humanize-errors [{:keys [errors value] :as _token}] (->> (map (fn [err] (case err @@ -72,9 +71,9 @@ (str/join "\n"))) (defn resolve-tokens+ - [tokens & {:keys [names-map? debug?] :as config}] + [tokens & {:keys [names-map?] :as config}] (p/let [sd-tokens (-> (wtt/token-names-tree tokens) - (resolve-sd-tokens+ config))] + (resolve-sd-tokens+))] (let [resolved-tokens (reduce (fn [acc ^js cur] (let [identifier (if names-map? @@ -99,8 +98,7 @@ :unit (:unit token-or-err)))] (assoc acc (wtt/token-identifier output-token) output-token))) {} sd-tokens)] - (when debug? - (js/console.log "Resolved tokens" resolved-tokens)) + (l/debug :hint "Resolved tokens" :js/tokens resolved-tokens) resolved-tokens))) ;; Hooks ----------------------------------------------------------------------- @@ -140,7 +138,6 @@ (defn use-resolved-workspace-tokens [& {:as config}] (-> (mf/deref refs/workspace-selected-token-set-tokens) - (doto js/console.log) (use-resolved-tokens config))) (defn use-active-theme-sets-tokens [& {:as config}] From e0e7b98ed79b83d51c551e9cceef955c1fc8eb50 Mon Sep 17 00:00:00 2001 From: Florian Schroedl Date: Wed, 18 Sep 2024 11:21:43 +0200 Subject: [PATCH 10/19] Docstring --- frontend/src/app/main/ui/workspace/tokens/tinycolor.cljs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/frontend/src/app/main/ui/workspace/tokens/tinycolor.cljs b/frontend/src/app/main/ui/workspace/tokens/tinycolor.cljs index 99fd64f84..91fac6bdf 100644 --- a/frontend/src/app/main/ui/workspace/tokens/tinycolor.cljs +++ b/frontend/src/app/main/ui/workspace/tokens/tinycolor.cljs @@ -1,7 +1,8 @@ (ns app.main.ui.workspace.tokens.tinycolor "Bindings for tinycolor2 which supports a wide range of css compatible colors. - Used by StyleDictionary, so we might as well use it directly." + This library was chosen as it is already used by StyleDictionary, + so there is no extra dependency cost and there was no clojure alternatives with all the necessary features." (:require ["tinycolor2" :as tinycolor])) From b68e7af84454b7b86bef8c03ebc33c2dcc5bb70b Mon Sep 17 00:00:00 2001 From: Florian Schroedl Date: Wed, 18 Sep 2024 11:27:30 +0200 Subject: [PATCH 11/19] Use tinycolor to convert hex color --- frontend/src/app/main/ui/workspace/tokens/sidebar.cljs | 5 ++--- frontend/src/app/main/ui/workspace/tokens/token.cljs | 7 +++++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/frontend/src/app/main/ui/workspace/tokens/sidebar.cljs b/frontend/src/app/main/ui/workspace/tokens/sidebar.cljs index 9240d62c3..b76b8e1df 100644 --- a/frontend/src/app/main/ui/workspace/tokens/sidebar.cljs +++ b/frontend/src/app/main/ui/workspace/tokens/sidebar.cljs @@ -71,9 +71,8 @@ :on-click on-click :on-context-menu on-context-menu :disabled errors?} - (js/console.log "resolved-value" resolved-value) - (when (wtt/color-token? token) - [:& color-bullet {:color (wtt/resolved-value-hex token) + (when-let [color (wtt/resolved-value-hex token)] + [:& color-bullet {:color color :mini? true}]) name])) diff --git a/frontend/src/app/main/ui/workspace/tokens/token.cljs b/frontend/src/app/main/ui/workspace/tokens/token.cljs index 6ddd84f22..5a6470349 100644 --- a/frontend/src/app/main/ui/workspace/tokens/token.cljs +++ b/frontend/src/app/main/ui/workspace/tokens/token.cljs @@ -2,7 +2,8 @@ (:require [app.common.data :as d] [clojure.set :as set] - [cuerdas.core :as str])) + [cuerdas.core :as str] + [app.main.ui.workspace.tokens.tinycolor :as tinycolor])) (defn get-workspace-tokens [state] @@ -199,4 +200,6 @@ (defn resolved-value-hex [{:keys [resolved-value] :as token}] (when (and resolved-value (color-token? token)) - (str "#" resolved-value))) + (some->> (tinycolor/valid-color resolved-value) + (tinycolor/->hex) + (str "#")))) From c007170603fca7221e78d5def0c64065925645da Mon Sep 17 00:00:00 2001 From: Florian Schroedl Date: Wed, 18 Sep 2024 11:28:31 +0200 Subject: [PATCH 12/19] Cleanup --- frontend/src/app/main/ui/workspace/tokens/errors.cljs | 1 - 1 file changed, 1 deletion(-) diff --git a/frontend/src/app/main/ui/workspace/tokens/errors.cljs b/frontend/src/app/main/ui/workspace/tokens/errors.cljs index 74ec8c335..65beb3774 100644 --- a/frontend/src/app/main/ui/workspace/tokens/errors.cljs +++ b/frontend/src/app/main/ui/workspace/tokens/errors.cljs @@ -36,7 +36,6 @@ (defn humanize-errors [errors] (->> errors (map (fn [err] - (js/console.log "err" err) (cond (:error/fn err) ((:error/fn err) (:error/value err)) (:error/message err) (:error/message err) From 48a8b1bc553920420617f453451bce15742790eb Mon Sep 17 00:00:00 2001 From: Florian Schroedl Date: Wed, 18 Sep 2024 11:30:32 +0200 Subject: [PATCH 13/19] Fix color updating --- frontend/src/app/main/ui/workspace/tokens/changes.cljs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/frontend/src/app/main/ui/workspace/tokens/changes.cljs b/frontend/src/app/main/ui/workspace/tokens/changes.cljs index 57d09f703..e1438da95 100644 --- a/frontend/src/app/main/ui/workspace/tokens/changes.cljs +++ b/frontend/src/app/main/ui/workspace/tokens/changes.cljs @@ -19,7 +19,8 @@ [app.main.ui.workspace.tokens.token :as wtt] [beicon.v2.core :as rx] [clojure.set :as set] - [potok.v2.core :as ptk])) + [potok.v2.core :as ptk] + [app.main.ui.workspace.tokens.tinycolor :as tinycolor])) ;; Token Updates --------------------------------------------------------------- @@ -126,7 +127,11 @@ (defn update-color [value shape-ids] - (wdc/change-fill shape-ids {:color (str "#" value)} 0)) + (let [color (some->> value + (tinycolor/valid-color) + (tinycolor/->hex) + (str "#"))] + (wdc/change-fill shape-ids {:color color} 0))) (defn update-shape-dimensions [value shape-ids attributes] (ptk/reify ::update-shape-dimensions From 061cd08e66886ba17510fa667566f3ac6ab53832 Mon Sep 17 00:00:00 2001 From: Florian Schroedl Date: Wed, 18 Sep 2024 11:43:35 +0200 Subject: [PATCH 14/19] Remove unused functions --- .../app/main/ui/workspace/tokens/token.cljs | 37 ------------------- 1 file changed, 37 deletions(-) diff --git a/frontend/src/app/main/ui/workspace/tokens/token.cljs b/frontend/src/app/main/ui/workspace/tokens/token.cljs index 5a6470349..5f1a95766 100644 --- a/frontend/src/app/main/ui/workspace/tokens/token.cljs +++ b/frontend/src/app/main/ui/workspace/tokens/token.cljs @@ -13,15 +13,6 @@ [token-id state] (get-in state [:workspace-data :tokens token-id])) -(def parseable-token-color-value-regexp - "Regexp that can be used to parse a hex value out of resolved token value. - This regexp also trims whitespace around the value." - #"^\s*#([A-Fa-f0-9]{3}|[A-Fa-f0-9]{6})\s*$") - -(defn parse-token-color-value [value] - (when-let [[_ hex] (re-find parseable-token-color-value-regexp value)] - {:value hex :unit :hex})) - (def parseable-token-value-regexp "Regexp that can be used to parse a number value out of resolved token value. This regexp also trims whitespace around the value." @@ -48,11 +39,6 @@ (defn token-identifier [{:keys [name] :as _token}] name) -(defn resolve-token-value [{:keys [value resolved-value] :as _token}] - (or - resolved-value - (d/parse-double value))) - (defn attributes-map "Creats an attributes map using collection of `attributes` for `id`." [attributes token] @@ -91,11 +77,6 @@ [token shapes token-attributes] (some #(token-applied? token % token-attributes) shapes)) -(defn shapes-token-applied-all? - "Test if `token` is applied to to any of `shapes` with at least one of the one of the given `token-attributes`." - [token shapes token-attributes] - (some #(token-applied? token % token-attributes) shapes)) - (defn shapes-ids-by-applied-attributes [token shapes token-attributes] (reduce (fn [acc shape] (let [applied-ids-by-attribute (->> (map #(when (token-attribute-applied? token shape %) @@ -109,24 +90,6 @@ (defn shapes-applied-all? [ids-by-attributes shape-ids attributes] (every? #(set/superset? (get ids-by-attributes %) shape-ids) attributes)) -(defn group-shapes-by-all-applied - [token shapes token-attributes] - (reduce - (fn [acc cur-shape] - (let [applied-attrs (token-applied-attributes token cur-shape token-attributes)] - (cond - (empty? applied-attrs) (update acc :none (fnil conj []) cur-shape) - (= applied-attrs token-attributes) (update acc :all (fnil conj []) cur-shape) - :else (reduce (fn [acc' cur'] - (update-in acc' [:some cur'] (fnil conj []) cur-shape)) - acc applied-attrs)))) - {} shapes)) - -(defn group-shapes-by-all-applied-all? [grouped-shapes] - (and (seq (:all grouped-shapes)) - (empty? (:other grouped-shapes)) - (empty? (:some grouped-shapes)))) - (defn token-name->path "Splits token-name into a path vector split by `.` characters. From 2a3fc9e7bdd566ab043f7cb92e6d2abbac2ef1bb Mon Sep 17 00:00:00 2001 From: Florian Schroedl Date: Wed, 18 Sep 2024 17:03:08 +0200 Subject: [PATCH 15/19] Pointer --- frontend/src/app/main/ui/workspace/tokens/form.scss | 1 + 1 file changed, 1 insertion(+) diff --git a/frontend/src/app/main/ui/workspace/tokens/form.scss b/frontend/src/app/main/ui/workspace/tokens/form.scss index 08df786fc..423683779 100644 --- a/frontend/src/app/main/ui/workspace/tokens/form.scss +++ b/frontend/src/app/main/ui/workspace/tokens/form.scss @@ -51,6 +51,7 @@ .color-bullet { margin-right: $s-8; + cursor: pointer; } .color-bullet-placeholder { From 6084c495821c57e4de62eef652bfa9afcde806eb Mon Sep 17 00:00:00 2001 From: Florian Schroedl Date: Wed, 18 Sep 2024 17:03:18 +0200 Subject: [PATCH 16/19] Share color picker effect to set hue slider css variables --- .../app/main/ui/workspace/colorpicker.cljs | 37 +++++++------- .../app/main/ui/workspace/tokens/form.cljs | 51 +++++++++++-------- 2 files changed, 50 insertions(+), 38 deletions(-) diff --git a/frontend/src/app/main/ui/workspace/colorpicker.cljs b/frontend/src/app/main/ui/workspace/colorpicker.cljs index 2170ebfeb..a76247538 100644 --- a/frontend/src/app/main/ui/workspace/colorpicker.cljs +++ b/frontend/src/app/main/ui/workspace/colorpicker.cljs @@ -52,6 +52,25 @@ ;; --- Color Picker Modal +(defn use-color-picker-css-variables! [node-ref current-color] + (mf/with-effect [current-color] + (let [node (mf/ref-val node-ref) + {:keys [r g b h v]} current-color + rgb [r g b] + hue-rgb (cc/hsv->rgb [h 1.0 255]) + hsl-from (cc/hsv->hsl [h 0.0 v]) + hsl-to (cc/hsv->hsl [h 1.0 v]) + + format-hsl (fn [[h s l]] + (str/fmt "hsl(%s, %s, %s)" + h + (str (* s 100) "%") + (str (* l 100) "%")))] + (dom/set-css-property! node "--color" (str/join ", " rgb)) + (dom/set-css-property! node "--hue-rgb" (str/join ", " hue-rgb)) + (dom/set-css-property! node "--saturation-grad-from" (format-hsl hsl-from)) + (dom/set-css-property! node "--saturation-grad-to" (format-hsl hsl-to))))) + (mf/defc colorpicker {::mf/props :obj} [{:keys [data disable-gradient disable-opacity disable-image on-change on-accept]}] @@ -220,23 +239,7 @@ (st/emit! (dc/update-colorpicker data))) ;; Updates the CSS color variable when there is a change in the color - (mf/with-effect [current-color] - (let [node (mf/ref-val node-ref) - {:keys [r g b h v]} current-color - rgb [r g b] - hue-rgb (cc/hsv->rgb [h 1.0 255]) - hsl-from (cc/hsv->hsl [h 0.0 v]) - hsl-to (cc/hsv->hsl [h 1.0 v]) - - format-hsl (fn [[h s l]] - (str/fmt "hsl(%s, %s, %s)" - h - (str (* s 100) "%") - (str (* l 100) "%")))] - (dom/set-css-property! node "--color" (str/join ", " rgb)) - (dom/set-css-property! node "--hue-rgb" (str/join ", " hue-rgb)) - (dom/set-css-property! node "--saturation-grad-from" (format-hsl hsl-from)) - (dom/set-css-property! node "--saturation-grad-to" (format-hsl hsl-to)))) + (use-color-picker-css-variables! node-ref current-color) ;; Updates color when pixel picker is used (mf/with-effect [picking-color? picked-color picked-color-select] diff --git a/frontend/src/app/main/ui/workspace/tokens/form.cljs b/frontend/src/app/main/ui/workspace/tokens/form.cljs index 83d80dfc1..da7eb68c3 100644 --- a/frontend/src/app/main/ui/workspace/tokens/form.cljs +++ b/frontend/src/app/main/ui/workspace/tokens/form.cljs @@ -7,18 +7,20 @@ (ns app.main.ui.workspace.tokens.form (:require-macros [app.main.style :as stl]) (:require - [app.main.ui.workspace.tokens.errors :as wte] ["lodash.debounce" :as debounce] - [app.common.colors :as cc] + [app.common.colors :as c] [app.common.data :as d] [app.main.data.modal :as modal] [app.main.data.tokens :as dt] [app.main.refs :as refs] [app.main.store :as st] [app.main.ui.components.color-bullet :refer [color-bullet]] + [app.main.ui.workspace.colorpicker :as colorpicker] [app.main.ui.workspace.colorpicker.ramp :refer [ramp-selector]] [app.main.ui.workspace.tokens.common :as tokens.common] + [app.main.ui.workspace.tokens.errors :as wte] [app.main.ui.workspace.tokens.style-dictionary :as sd] + [app.main.ui.workspace.tokens.tinycolor :as tinycolor] [app.main.ui.workspace.tokens.token :as wtt] [app.main.ui.workspace.tokens.update :as wtu] [app.util.dom :as dom] @@ -26,8 +28,7 @@ [malli.core :as m] [malli.error :as me] [promesa.core :as p] - [rumext.v2 :as mf] - [app.main.ui.workspace.tokens.tinycolor :as tinycolor])) + [rumext.v2 :as mf])) ;; Schemas --------------------------------------------------------------------- @@ -155,21 +156,30 @@ Token names should only contain letters and digits separated by . characters.")} (mf/defc ramp [{:keys [color on-change]}] - (let [dragging? (mf/use-state) - [r g b] (cc/hex->rgb color) - [h s v] (cc/hex->hsv color) - value (mf/use-state {:hex color - :r r :g g :b b - :h h :s s :v v}) - on-change' (fn [color] - (swap! value merge color) - (when-not (and @dragging? (:hex color)) - (on-change (:hex color))))] - [:& ramp-selector {:color @value - :disable-opacity true - :on-start-drag #(reset! dragging? true) - :on-finish-drag #(reset! dragging? false) - :on-change on-change'}])) + (let [wrapper-node-ref (mf/use-ref nil) + dragging? (mf/use-state) + hex->value (fn [hex] + (when-let [tc (tinycolor/valid-color hex)] + (let [hex (str "#" (tinycolor/->hex tc)) + [r g b] (c/hex->rgb hex) + [h s v] (c/hex->hsv hex)] + {:hex hex + :r r :g g :b b + :h h :s s :v v + :alpha 1}))) + value (mf/use-state (hex->value color)) + on-change' (fn [{:keys [hex]}] + (reset! value (hex->value hex)) + (when-not (and @dragging? hex) + (on-change hex)))] + (colorpicker/use-color-picker-css-variables! wrapper-node-ref @value) + [:div {:ref wrapper-node-ref} + [:& ramp-selector + {:color @value + :disable-opacity true + :on-start-drag #(reset! dragging? true) + :on-finish-drag #(reset! dragging? false) + :on-change on-change'}]])) (mf/defc token-value-or-errors [{:keys [result-or-errors]}] @@ -343,8 +353,7 @@ Token names should only contain letters and digits separated by . characters.")} [:div {:class (stl/css :color-bullet-placeholder)}])]))}] (when @color-ramp-open? [:& ramp {:color (some-> (or @token-resolve-result (:value token)) - (tinycolor/valid-color) - (tinycolor/->hex)) + (tinycolor/valid-color)) :on-change on-update-color}]) [:& token-value-or-errors {:result-or-errors @token-resolve-result}] From 8804d1432efee8a0934d3d1323690384141fb0b2 Mon Sep 17 00:00:00 2001 From: Florian Schroedl Date: Wed, 18 Sep 2024 17:15:45 +0200 Subject: [PATCH 17/19] Update the input field value when chosing color from color ramp --- frontend/src/app/main/ui/workspace/tokens/form.cljs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/frontend/src/app/main/ui/workspace/tokens/form.cljs b/frontend/src/app/main/ui/workspace/tokens/form.cljs index da7eb68c3..079f5189f 100644 --- a/frontend/src/app/main/ui/workspace/tokens/form.cljs +++ b/frontend/src/app/main/ui/workspace/tokens/form.cljs @@ -244,6 +244,7 @@ Token names should only contain letters and digits separated by . characters.")} ;; Value color (mf/use-state (when color? (:value token))) color-ramp-open? (mf/use-state false) + value-input-ref (mf/use-ref nil) value-ref (mf/use-var (:value token)) token-resolve-result (mf/use-state (get-in resolved-tokens [(wtt/token-identifier token) :resolved-value])) set-resolve-value (mf/use-callback @@ -265,6 +266,7 @@ Token names should only contain letters and digits separated by . characters.")} (mf/deps on-update-value-debounced) (fn [hex-value] (reset! value-ref hex-value) + (set! (.-value (mf/ref-val value-input-ref)) hex-value) (on-update-value-debounced hex-value))) value-error? (seq (:errors @token-resolve-result)) valid-value-field? (and @@ -342,7 +344,8 @@ Token names should only contain letters and digits separated by . characters.")} [:& tokens.common/labeled-input {:label "Value" :input-props {:default-value @value-ref :on-blur on-update-value - :on-change on-update-value} + :on-change on-update-value + :ref value-input-ref} :render-right (when color? (mf/fnc [] [:div {:class (stl/css :color-bullet) From f5b62a5fc1b14556bc8c81b29a68ab430db0371b Mon Sep 17 00:00:00 2001 From: Florian Schroedl Date: Wed, 18 Sep 2024 17:23:42 +0200 Subject: [PATCH 18/19] Style the form to fit the color ramp exactly --- frontend/src/app/main/ui/workspace/tokens/form.cljs | 3 ++- frontend/src/app/main/ui/workspace/tokens/form.scss | 6 +++++- frontend/src/app/main/ui/workspace/tokens/modals.scss | 3 +++ 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/frontend/src/app/main/ui/workspace/tokens/form.cljs b/frontend/src/app/main/ui/workspace/tokens/form.cljs index 079f5189f..b202c3ac8 100644 --- a/frontend/src/app/main/ui/workspace/tokens/form.cljs +++ b/frontend/src/app/main/ui/workspace/tokens/form.cljs @@ -326,7 +326,8 @@ Token names should only contain letters and digits separated by . characters.")} (st/emit! (wtu/update-workspace-tokens)) (modal/hide!)))))))))] [:form - {:on-submit on-submit} + {:class (stl/css :form-wrapper) + :on-submit on-submit} [:div {:class (stl/css :token-rows)} [:div [:& tokens.common/labeled-input {:label "Name" diff --git a/frontend/src/app/main/ui/workspace/tokens/form.scss b/frontend/src/app/main/ui/workspace/tokens/form.scss index 423683779..4d1b37c86 100644 --- a/frontend/src/app/main/ui/workspace/tokens/form.scss +++ b/frontend/src/app/main/ui/workspace/tokens/form.scss @@ -7,6 +7,10 @@ @import "refactor/common-refactor.scss"; @import "./common.scss"; +.form-wrapper { + width: $s-260; +} + .button-row { display: flex; flex-direction: column; @@ -30,7 +34,7 @@ @include bodySmallTypography; padding: $s-4 $s-6; font-weight: medium; - height: $s-24; + min-height: 1lh; color: var(--color-foreground-primary); border: 1px solid color-mix(in hsl, var(--color-foreground-secondary) 30%, transparent); diff --git a/frontend/src/app/main/ui/workspace/tokens/modals.scss b/frontend/src/app/main/ui/workspace/tokens/modals.scss index c0e045448..cb16e1ec2 100644 --- a/frontend/src/app/main/ui/workspace/tokens/modals.scss +++ b/frontend/src/app/main/ui/workspace/tokens/modals.scss @@ -8,6 +8,9 @@ .shadow { @extend .modal-container-base; + width: auto; + max-width: auto; + min-width: auto; @include menuShadow; position: absolute; z-index: 11; From 5b7b343f62d0c12f12f10a4db9238a4e1fa7482a Mon Sep 17 00:00:00 2001 From: Florian Schroedl Date: Wed, 18 Sep 2024 17:25:55 +0200 Subject: [PATCH 19/19] Cleanup --- frontend/src/app/main/ui/workspace/colorpicker/ramp.cljs | 1 - 1 file changed, 1 deletion(-) diff --git a/frontend/src/app/main/ui/workspace/colorpicker/ramp.cljs b/frontend/src/app/main/ui/workspace/colorpicker/ramp.cljs index cc70d887c..970525d3c 100644 --- a/frontend/src/app/main/ui/workspace/colorpicker/ramp.cljs +++ b/frontend/src/app/main/ui/workspace/colorpicker/ramp.cljs @@ -52,7 +52,6 @@ (mf/defc ramp-selector [{:keys [color disable-opacity on-change on-start-drag on-finish-drag]}] - (js/console.log "color" color) (let [{hex :hex hue :h saturation :s value :v alpha :alpha} color