diff --git a/CHANGES.md b/CHANGES.md index 538c8994f4..86c535adcc 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -9,6 +9,8 @@ ### :sparkles: New features & Enhancements - Add MCP server integration [Taiga #13112](https://tree.taiga.io/project/penpot/us/13112), [Taiga #13114](https://tree.taiga.io/project/penpot/us/13114) +- Access Tokens look & feel refinement [Taiga #13114](https://tree.taiga.io/project/penpot/us/13114) +- Enhance readability of applied tokens in plugins API [Taiga #13714](https://tree.taiga.io/project/penpot/issue/13714) ### :bug: Bugs fixed diff --git a/frontend/src/app/main/data/workspace/tokens/application.cljs b/frontend/src/app/main/data/workspace/tokens/application.cljs index 686cd866d0..6f52e92df9 100644 --- a/frontend/src/app/main/data/workspace/tokens/application.cljs +++ b/frontend/src/app/main/data/workspace/tokens/application.cljs @@ -49,14 +49,14 @@ ;; (note that dwsh/update-shapes function returns an event) -(defn update-shape-radius-all - ([value shape-ids attributes] (update-shape-radius-all value shape-ids attributes nil)) - ([value shape-ids _attributes page-id] ; The attributes param is needed to have the same arity that other update functions +(defn update-shape-radius + ([value shape-ids attributes] (update-shape-radius value shape-ids attributes nil)) + ([value shape-ids attributes page-id] ; The attributes param is needed to have the same arity that other update functions (when (number? value) (let [value (max 0 value)] (dwsh/update-shapes shape-ids (fn [shape] - (ctsr/set-radius-to-all-corners shape value)) + (ctsr/set-radius-for-corners shape attributes value)) {:reg-objects? true :ignore-touched true :page-id page-id @@ -531,7 +531,7 @@ (some attributes #{:r1 :r2 :r3 :r4}) (conj #(if (= attributes #{:r1 :r2 :r3 :r4}) - (update-shape-radius-all value shape-ids attributes page-id) + (update-shape-radius value shape-ids attributes page-id) (update-shape-radius-for-corners value shape-ids (set (filter attributes #{:r1 :r2 :r3 :r4})) @@ -862,7 +862,7 @@ :border-radius {:title "Border Radius" :attributes ctt/border-radius-keys - :on-update-shape update-shape-radius-all + :on-update-shape update-shape-radius :modal {:key :tokens/border-radius :fields [{:label "Border Radius" :key :border-radius}]}} diff --git a/frontend/src/app/main/ui/workspace/tokens/management/context_menu.cljs b/frontend/src/app/main/ui/workspace/tokens/management/context_menu.cljs index bcb44b83c5..eb43f4a23b 100644 --- a/frontend/src/app/main/ui/workspace/tokens/management/context_menu.cljs +++ b/frontend/src/app/main/ui/workspace/tokens/management/context_menu.cljs @@ -290,7 +290,7 @@ :r4 "Bottom Left" :r3 "Bottom Right"} :hint (tr "workspace.tokens.radius") - :on-update-shape-all dwta/update-shape-radius-all + :on-update-shape-all dwta/update-shape-radius :on-update-shape update-shape-radius-for-corners}) shadow (partial generic-attribute-actions #{:shadow} "Shadow")] {:border-radius border-radius diff --git a/frontend/src/app/plugins/shape.cljs b/frontend/src/app/plugins/shape.cljs index c7730d8a36..9075448ca8 100644 --- a/frontend/src/app/plugins/shape.cljs +++ b/frontend/src/app/plugins/shape.cljs @@ -31,7 +31,6 @@ [app.common.types.shape.radius :as ctsr] [app.common.types.shape.shadow :as ctss] [app.common.types.text :as txt] - [app.common.types.token :as cto] [app.common.uuid :as uuid] [app.main.data.plugins :as dp] [app.main.data.workspace :as dw] @@ -55,6 +54,7 @@ [app.plugins.register :as r] [app.plugins.ruler-guides :as rg] [app.plugins.text :as text] + [app.plugins.tokens :refer [resolve-tokens translate-prop token-attr?]] [app.plugins.utils :as u] [app.util.http :as http] [app.util.object :as obj] @@ -1300,7 +1300,8 @@ (fn [_] (let [tokens (-> (u/locate-shape file-id page-id id) - (get :applied-tokens))] + (get :applied-tokens) + (resolve-tokens))] (reduce (fn [acc [prop name]] (obj/set! acc (json/write-camel-key prop) name)) @@ -1311,11 +1312,11 @@ {:enumerable false :schema [:tuple [:fn token-proxy?] - [:maybe [:set [:and ::sm/keyword [:fn cto/token-attr?]]]]] + [:maybe [:set [:and ::sm/keyword [:fn token-attr?]]]]] :fn (fn [token attrs] (let [token (u/locate-token file-id (obj/get token "$set-id") (obj/get token "$id")) - kw-attrs (into #{} (map keyword attrs))] - (if (some #(not (cto/token-attr? %)) kw-attrs) + kw-attrs (into #{} (map (comp translate-prop keyword) attrs))] + (if (some #(not (token-attr? %)) kw-attrs) (u/display-not-valid :applyToken attrs) (st/emit! (dwta/toggle-token {:token token diff --git a/frontend/src/app/plugins/tokens.cljs b/frontend/src/app/plugins/tokens.cljs index 268652e334..281b82fbc9 100644 --- a/frontend/src/app/plugins/tokens.cljs +++ b/frontend/src/app/plugins/tokens.cljs @@ -19,18 +19,53 @@ [app.main.store :as st] [app.plugins.utils :as u] [app.util.object :as obj] - [clojure.datafy :refer [datafy]])) + [clojure.datafy :refer [datafy]] + [clojure.set :refer [map-invert]] + [cuerdas.core :as str])) ;; === Token +(def token-name-mapping + {:r1 :borderRadiusTopLeft + :r2 :borderRadiusTopRight + :r3 :borderRadiusBottomRight + :r4 :borderRadiusBottomLeft + + :p1 :paddingTopLeft + :p2 :paddingTopRight + :p3 :paddingBottomRight + :p4 :paddingBottomLeft + + :m1 :marginTopLeft + :m2 :marginTopRight + :m3 :marginBottomRight + :m4 :marginBottomLeft}) + +(def name-token-mapping + (map-invert token-name-mapping)) + +(defn resolve-prop + [k] + (get token-name-mapping k k)) + +(defn translate-prop + [k] + (let [k (-> (str/camel k) keyword)] + (get name-token-mapping k k))) + +(defn token-attr? + [attr] + (cto/token-attr? (translate-prop attr))) + (defn- apply-token-to-shapes [file-id set-id id shape-ids attrs] + (let [token (u/locate-token file-id set-id id)] - (if (some #(not (cto/token-attr? %)) attrs) + (if (some #(not (token-attr? %)) attrs) (u/display-not-valid :applyToSelected attrs) (st/emit! (dwta/toggle-token {:token token - :attrs attrs + :attrs (into #{} (map translate-prop) attrs) :shape-ids shape-ids :expand-with-children false}))))) @@ -42,6 +77,13 @@ (ts/tokenscript-symbols->penpot-unit))] resolved-value)) + +(defn resolve-tokens + [value] + (into {} + (map (fn [[k v]] [(resolve-prop k) v])) + value)) + (defn token-proxy? [p] (obj/type-of? p "TokenProxy")) @@ -146,13 +188,13 @@ {:enumerable false :schema [:tuple [:vector [:fn shape-proxy?]] - [:maybe [:set [:and ::sm/keyword [:fn cto/token-attr?]]]]] + [:maybe [:set [:and ::sm/keyword [:fn token-attr?]]]]] :fn (fn [shapes attrs] (apply-token-to-shapes file-id set-id id (map #(obj/get % "$id") shapes) attrs))} :applyToSelected {:enumerable false - :schema [:tuple [:maybe [:set [:and ::sm/keyword [:fn cto/token-attr?]]]]] + :schema [:tuple [:maybe [:set [:and ::sm/keyword [:fn token-attr?]]]]] :fn (fn [attrs] (let [selected (get-in @st/state [:workspace-local :selected])] (apply-token-to-shapes file-id set-id id selected attrs)))})) diff --git a/frontend/test/frontend_tests/logic/components_and_tokens.cljs b/frontend/test/frontend_tests/logic/components_and_tokens.cljs index 689ac76b63..9e830c9a76 100644 --- a/frontend/test/frontend_tests/logic/components_and_tokens.cljs +++ b/frontend/test/frontend_tests/logic/components_and_tokens.cljs @@ -141,7 +141,7 @@ events [(dwta/apply-token {:shape-ids [(cthi/id :frame1)] :attributes #{:r1 :r2 :r3 :r4} :token (toht/get-token file "test-token-2") - :on-update-shape dwta/update-shape-radius-all})] + :on-update-shape dwta/update-shape-radius})] step2 (fn [_] (let [events2 [(dwl/sync-file (:id file) (:id file))]] @@ -249,11 +249,11 @@ events [(dwta/apply-token {:shape-ids [(cthi/id :c-frame1)] :attributes #{:r1 :r2 :r3 :r4} :token (toht/get-token file "test-token-2") - :on-update-shape dwta/update-shape-radius-all}) + :on-update-shape dwta/update-shape-radius}) (dwta/apply-token {:shape-ids [(cthi/id :frame1)] :attributes #{:r1 :r2 :r3 :r4} :token (toht/get-token file "test-token-3") - :on-update-shape dwta/update-shape-radius-all})] + :on-update-shape dwta/update-shape-radius})] step2 (fn [_] (let [events2 [(dwl/sync-file (:id file) (:id file))]] @@ -293,7 +293,7 @@ (dwta/apply-token {:shape-ids [(cthi/id :frame1)] :attributes #{:r1 :r2 :r3 :r4} :token (toht/get-token file "test-token-3") - :on-update-shape dwta/update-shape-radius-all})] + :on-update-shape dwta/update-shape-radius})] step2 (fn [_] (let [events2 [(dwl/sync-file (:id file) (:id file))]] diff --git a/frontend/test/frontend_tests/tokens/logic/token_actions_test.cljs b/frontend/test/frontend_tests/tokens/logic/token_actions_test.cljs index cb6f2e39d8..e468e420bb 100644 --- a/frontend/test/frontend_tests/tokens/logic/token_actions_test.cljs +++ b/frontend/test/frontend_tests/tokens/logic/token_actions_test.cljs @@ -64,7 +64,7 @@ events [(dwta/apply-token {:shape-ids [(:id rect-1)] :attributes #{:r1 :r2 :r3 :r4} :token (toht/get-token file "borderRadius.md") - :on-update-shape dwta/update-shape-radius-all})]] + :on-update-shape dwta/update-shape-radius})]] (tohs/run-store-async store done events (fn [new-state] @@ -89,11 +89,11 @@ events [(dwta/apply-token {:shape-ids [(:id rect-1)] :attributes #{:r1 :r2 :r3 :r4} :token (toht/get-token file "borderRadius.sm") - :on-update-shape dwta/update-shape-radius-all}) + :on-update-shape dwta/update-shape-radius}) (dwta/apply-token {:shape-ids [(:id rect-1)] :attributes #{:r1 :r2 :r3 :r4} :token (toht/get-token file "borderRadius.md") - :on-update-shape dwta/update-shape-radius-all})]] + :on-update-shape dwta/update-shape-radius})]] (tohs/run-store-async store done events (fn [new-state] @@ -117,14 +117,14 @@ (dwta/apply-token {:attributes #{:r1 :r2 :r3 :r4} :token (toht/get-token file "borderRadius.sm") :shape-ids [(:id rect-1)] - :on-update-shape dwta/update-shape-radius-all}) + :on-update-shape dwta/update-shape-radius}) ;; Apply single `:r1` attribute to same shape ;; while removing other attributes from the border-radius set ;; but keep `:r4` for testing purposes (dwta/apply-token {:attributes #{:r1 :r2 :r3} :token (toht/get-token file "borderRadius.md") :shape-ids [(:id rect-1)] - :on-update-shape dwta/update-shape-radius-all})]] + :on-update-shape dwta/update-shape-radius})]] (tohs/run-store-async store done events (fn [new-state] @@ -153,7 +153,7 @@ (dwta/apply-token {:shape-ids [(:id rect-2)] :attributes #{:r1 :r2 :r3 :r4} :token (toht/get-token file "borderRadius.sm") - :on-update-shape dwta/update-shape-radius-all})]] + :on-update-shape dwta/update-shape-radius})]] (tohs/run-store-async store done events (fn [new-state] @@ -762,7 +762,7 @@ rect-2 (cths/get-shape file :rect-2) events [(dwta/toggle-token {:shape-ids [(:id rect-1) (:id rect-2)] :token-type-props {:attributes #{:r1 :r2 :r3 :r4} - :on-update-shape dwta/update-shape-radius-all} + :on-update-shape dwta/update-shape-radius} :token (toht/get-token file "borderRadius.md")})]] (tohs/run-store-async store done events diff --git a/plugins/libs/plugin-types/index.d.ts b/plugins/libs/plugin-types/index.d.ts index 381de47fc7..84cff58440 100644 --- a/plugins/libs/plugin-types/index.d.ts +++ b/plugins/libs/plugin-types/index.d.ts @@ -5231,7 +5231,11 @@ export interface TokenTheme { /** * The properties that a BorderRadius token can be applied to. */ -type TokenBorderRadiusProps = 'r1' | 'r2' | 'r3' | 'r4'; +type TokenBorderRadiusProps = + | 'borderRadiusTopLeft' + | 'borderRadiusTopRight' + | 'borderRadiusBottomRight' + | 'borderRadiusBottomLeft'; /** * The properties that a Shadow token can be applied to. @@ -5307,16 +5311,16 @@ type TokenSpacingProps = | 'columnGap' // Spacing / Padding - | 'p1' - | 'p2' - | 'p3' - | 'p4' + | 'paddingLeft' + | 'paddingTop' + | 'paddingRight' + | 'paddingBottom' // Spacing / Margin - | 'm1' - | 'm2' - | 'm3' - | 'm4'; + | 'marginLeft' + | 'marginTop' + | 'marginRight' + | 'marginBottom'; /** * The properties that a BorderWidth token can be applied to.