Remap token properties for usability

This commit is contained in:
alonso.torres 2026-03-12 12:14:25 +01:00 committed by Alonso Torres
parent 46c2d41218
commit 4e1b940e04
8 changed files with 86 additions and 37 deletions

View File

@ -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

View File

@ -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}]}}

View File

@ -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

View File

@ -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

View File

@ -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)))}))

View File

@ -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))]]

View File

@ -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

View File

@ -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.