Apply tokens to stroke per side

This commit is contained in:
Luis de Dios 2026-07-29 10:37:19 +02:00
parent 7f2dc66e86
commit ddd493bd3e
11 changed files with 256 additions and 101 deletions

View File

@ -269,8 +269,11 @@
(def spacing-keys (schema-keys schema:spacing)) (def spacing-keys (schema-keys schema:spacing))
(def ^:private schema:stroke-width (def ^:private schema:stroke-width
[:map [:map {:title "StrokeWidthTokenAttrs"}
[:stroke-width {:optional true} schema:token-name]]) [:stroke-width-top {:optional true} schema:token-name]
[:stroke-width-right {:optional true} schema:token-name]
[:stroke-width-bottom {:optional true} schema:token-name]
[:stroke-width-left {:optional true} schema:token-name]])
(def stroke-width-keys (schema-keys schema:stroke-width)) (def stroke-width-keys (schema-keys schema:stroke-width))
@ -421,6 +424,10 @@
:fill :fills :fill :fills
:stroke-color :strokes :stroke-color :strokes
:stroke-width :strokes :stroke-width :strokes
:stroke-width-top :strokes
:stroke-width-right :strokes
:stroke-width-bottom :strokes
:stroke-width-left :strokes
token-attr)) token-attr))
(defn shape-attr->token-attrs (defn shape-attr->token-attrs
@ -434,12 +441,16 @@
#{:fill} #{:fill}
(and (= :strokes shape-attr) (nil? changed-sub-attr)) (and (= :strokes shape-attr) (nil? changed-sub-attr))
#{:stroke-width :stroke-color} (set/union stroke-width-keys #{:stroke-color})
(= :strokes shape-attr) (= :strokes shape-attr)
(cond (let [sub-attrs (set changed-sub-attr)]
(some #{:stroke-color} changed-sub-attr) #{:stroke-color} (cond
(some #{:stroke-width} changed-sub-attr) #{:stroke-width}) (sub-attrs :stroke-color) #{:stroke-color}
(sub-attrs :stroke-width) stroke-width-keys
:else
(let [per-side (set/intersection sub-attrs stroke-width-keys)]
(when (seq per-side) per-side))))
(= :layout-padding shape-attr) (= :layout-padding shape-attr)
(if (seq changed-sub-attr) (if (seq changed-sub-attr)
@ -460,6 +471,7 @@
(font-weight-keys shape-attr) #{shape-attr :typography} (font-weight-keys shape-attr) #{shape-attr :typography}
(border-radius-keys shape-attr) #{shape-attr} (border-radius-keys shape-attr) #{shape-attr}
(stroke-width-keys shape-attr) #{shape-attr}
(shadow-keys shape-attr) #{shape-attr} (shadow-keys shape-attr) #{shape-attr}
(sizing-keys shape-attr) #{shape-attr} (sizing-keys shape-attr) #{shape-attr}
(opacity-keys shape-attr) #{shape-attr} (opacity-keys shape-attr) #{shape-attr}
@ -555,6 +567,10 @@
:line-height [:line-height :number] :line-height [:line-height :number]
:opacity [:opacity] :opacity [:opacity]
:stroke-width [:stroke-width :dimensions] :stroke-width [:stroke-width :dimensions]
:stroke-width-top [:stroke-width :dimensions]
:stroke-width-right [:stroke-width :dimensions]
:stroke-width-bottom [:stroke-width :dimensions]
:stroke-width-left [:stroke-width :dimensions]
:font-size [:font-size] :font-size [:font-size]
:font-weight [:font-weight] :font-weight [:font-weight]
:text-decoration [:text-decoration] :text-decoration [:text-decoration]

View File

@ -102,20 +102,57 @@
:no-wasm? true}))))))) :no-wasm? true})))))))
(defn update-stroke-width (defn update-stroke-width
([value shape-ids attributes] (update-stroke-width value shape-ids attributes nil)) ([value shape-ids attributes]
([value shape-ids _attributes page-id] ; The attributes param is needed to have the same arity that other update functions (update-stroke-width value shape-ids attributes nil))
([value shape-ids _attributes page-id]
(when (number? value) (when (number? value)
(dwsh/update-shapes shape-ids (dwsh/update-shapes shape-ids
(fn [shape] (fn [shape]
(if (seq (:strokes shape)) (if (seq (:strokes shape))
(assoc-in shape [:strokes 0 :stroke-width] value) (let [stroke (get-in shape [:strokes 0])]
(let [stroke (assoc cts/default-stroke :stroke-width value)] (assoc-in shape [:strokes 0]
(merge stroke
{:stroke-width value
:stroke-width-top value
:stroke-width-right value
:stroke-width-bottom value
:stroke-width-left value})))
(let [stroke (assoc cts/default-stroke
:stroke-width value
:stroke-width-top value
:stroke-width-right value
:stroke-width-bottom value
:stroke-width-left value)]
(assoc shape :strokes [stroke])))) (assoc shape :strokes [stroke]))))
{:reg-objects? true {:reg-objects? true
:ignore-touched true :ignore-touched true
:page-id page-id :page-id page-id
:attrs [:strokes]})))) :attrs [:strokes]}))))
(defn update-stroke-width-side
([value shape-ids attributes]
(update-stroke-width-side value shape-ids attributes nil))
([value shape-ids attributes page-id]
(when (number? value)
(let [attrs (into {} (map (fn [attr] [attr value]) attributes))]
(dwsh/update-shapes shape-ids
(fn [shape]
(if (seq (:strokes shape))
(let [attrs (if (contains? attributes :stroke-width-top)
(assoc attrs :stroke-width value)
attrs)]
(update-in shape [:strokes 0] merge attrs))
(let [default-attrs (reduce
(fn [acc attr]
(assoc acc attr value))
{:stroke-width value}
(disj attributes :stroke-width))]
(assoc shape :strokes [(merge cts/default-stroke default-attrs)]))))
{:reg-objects? true
:ignore-touched true
:page-id page-id
:attrs [:strokes]})))))
(defn update-color [f value shape-ids page-id] (defn update-color [f value shape-ids page-id]
(when-let [tc (tinycolor/valid-color value)] (when-let [tc (tinycolor/valid-color value)]
(let [hex (tinycolor/->hex-string tc) (let [hex (tinycolor/->hex-string tc)
@ -539,10 +576,10 @@
(set (filter attributes #{:r1 :r2 :r3 :r4})) (set (filter attributes #{:r1 :r2 :r3 :r4}))
page-id))) page-id)))
(some attributes #{:stroke-width}) (some attributes ctt/stroke-width-keys)
(conj #(update-stroke-width (conj #(update-stroke-width-side
value shape-ids value shape-ids
#{:stroke-width} (set/intersection attributes ctt/stroke-width-keys)
page-id)) page-id))
(some attributes #{:max-width :max-height :layout-item-max-h :layout-item-max-w :layout-item-min-h :layout-item-min-w}) (some attributes #{:max-width :max-height :layout-item-max-h :layout-item-max-w :layout-item-min-h :layout-item-min-w})
@ -615,9 +652,9 @@
"Maps each attribute-set to the update function that applies it to a shape. "Maps each attribute-set to the update function that applies it to a shape.
Used both here (to resolve the correct update fn when explicit attrs are Used both here (to resolve the correct update fn when explicit attrs are
passed to toggle-token) and in propagation.cljs (re-exported from there)." passed to toggle-token) and in propagation.cljs (re-exported from there)."
{ctt/border-radius-keys update-shape-radius-for-corners {ctt/border-radius-keys update-shape-radius-for-corners
ctt/color-keys update-fill-stroke ctt/color-keys update-fill-stroke
ctt/stroke-width-keys update-stroke-width ctt/stroke-width-keys update-stroke-width-side
ctt/sizing-keys apply-dimensions-token ctt/sizing-keys apply-dimensions-token
ctt/opacity-keys update-opacity ctt/opacity-keys update-opacity
ctt/rotation-keys update-rotation ctt/rotation-keys update-rotation
@ -1006,6 +1043,7 @@
{:title "Stroke Width" {:title "Stroke Width"
:attributes ctt/stroke-width-keys :attributes ctt/stroke-width-keys
:on-update-shape update-stroke-width :on-update-shape update-stroke-width
:on-update-shape-side update-stroke-width-side
:modal {:key :tokens/stroke-width :modal {:key :tokens/stroke-width
:fields [{:label "Stroke Width" :fields [{:label "Stroke Width"
:key :stroke-width}]}} :key :stroke-width}]}}

View File

@ -145,7 +145,7 @@
[:step {:optional true} [:maybe [:or :int :float]]] [:step {:optional true} [:maybe [:or :int :float]]]
[:is-selected-on-focus {:optional true} :boolean] [:is-selected-on-focus {:optional true} :boolean]
[:nillable {:optional true} :boolean] [:nillable {:optional true} :boolean]
[:applied-token {:optional true} [:maybe [:or :string [:= :multiple]]]] [:applied-token-name {:optional true} [:maybe [:or :string [:= :multiple]]]]
[:empty-to-end {:optional true} :boolean] [:empty-to-end {:optional true} :boolean]
[:on-change {:optional true} fn?] [:on-change {:optional true} fn?]
[:on-change-start {:optional true} fn?] [:on-change-start {:optional true} fn?]

View File

@ -276,7 +276,7 @@
(seq strokes) (seq strokes)
[:> h/sortable-container* {} [:> h/sortable-container* {}
(for [[index value] (d/enumerate (:strokes values []))] (for [[index value] (d/enumerate (:strokes values []))]
[:> stroke-row* {:key (dm/str "stroke-" index "-" (hash applied-tokens)) [:> stroke-row* {:key (dm/str "stroke-" index)
:index index :index index
:stroke value :stroke value
:title (tr "workspace.options.stroke-color") :title (tr "workspace.options.stroke-color")

View File

@ -121,6 +121,25 @@
show-multiple-placeholder? (or per-side-expanded? (not all-sides-equal?)) show-multiple-placeholder? (or per-side-expanded? (not all-sides-equal?))
applied-token-width
(mf/with-memo [applied-tokens]
(let [top (get applied-tokens :stroke-width-top)
right (get applied-tokens :stroke-width-right)
bottom (get applied-tokens :stroke-width-bottom)
left (get applied-tokens :stroke-width-left)
per-side [top right bottom left]
per-side-has-token? (some some? per-side)]
(cond
(and (every? some? per-side) (apply = per-side))
(first per-side)
per-side-has-token?
:multiple
:else
nil)))
per-side-toggle-label per-side-toggle-label
(if per-side-disabled (if per-side-disabled
(tr "workspace.options.stroke.per-side-disabled") (tr "workspace.options.stroke.per-side-disabled")
@ -139,42 +158,62 @@
on-width-top-change on-width-top-change
(mf/use-fn (mf/use-fn
(mf/deps index on-stroke-width-side-change) (mf/deps index on-stroke-width-side-change ids)
#(on-stroke-width-side-change index :stroke-width-top %)) #(soc/emit-value-or-token % (fn [v]
(on-stroke-width-side-change index :stroke-width-top v)) ids #{:stroke-width-top}))
on-width-right-change on-width-right-change
(mf/use-fn (mf/use-fn
(mf/deps index on-stroke-width-side-change) (mf/deps index on-stroke-width-side-change ids)
#(on-stroke-width-side-change index :stroke-width-right %)) #(soc/emit-value-or-token % (fn [v]
(on-stroke-width-side-change index :stroke-width-right v)) ids #{:stroke-width-right}))
on-width-bottom-change on-width-bottom-change
(mf/use-fn (mf/use-fn
(mf/deps index on-stroke-width-side-change) (mf/deps index on-stroke-width-side-change ids)
#(on-stroke-width-side-change index :stroke-width-bottom %)) #(soc/emit-value-or-token % (fn [v]
(on-stroke-width-side-change index :stroke-width-bottom v)) ids #{:stroke-width-bottom}))
on-width-left-change on-width-left-change
(mf/use-fn (mf/use-fn
(mf/deps index on-stroke-width-side-change) (mf/deps index on-stroke-width-side-change ids)
#(on-stroke-width-side-change index :stroke-width-left %)) #(soc/emit-value-or-token % (fn [v]
(on-stroke-width-side-change index :stroke-width-left v)) ids #{:stroke-width-left}))
on-width-change on-width-change
(mf/use-fn (mf/use-fn
(mf/deps index on-stroke-width-change ids per-side?) (mf/deps index on-stroke-width-change ids per-side?)
(fn [value] (fn [value]
(if per-side? (if per-side?
(st/emit! (dc/change-stroke-attrs (if (coll? value)
ids (soc/emit-value-or-token
{:stroke-width value value
:stroke-width-top value (fn [v]
:stroke-width-right value (st/emit! (dc/change-stroke-attrs
:stroke-width-bottom value ids
:stroke-width-left value} {:stroke-width v
index)) :stroke-width-top v
:stroke-width-right v
:stroke-width-bottom v
:stroke-width-left v}
index)))
ids
#{:stroke-width-top :stroke-width-right
:stroke-width-bottom :stroke-width-left})
(st/emit! (dc/change-stroke-attrs
ids
{:stroke-width value
:stroke-width-top value
:stroke-width-right value
:stroke-width-bottom value
:stroke-width-left value}
index)))
(soc/emit-value-or-token (soc/emit-value-or-token
value value
#(on-stroke-width-change index %) #(on-stroke-width-change index %)
ids ids
#{:stroke-width})))) #{:stroke-width-top :stroke-width-right
:stroke-width-bottom :stroke-width-left}))))
;; The SVG renderer defaults dash and gap to `stroke-width + 10` when ;; The SVG renderer defaults dash and gap to `stroke-width + 10` when
;; unset. Showing that value as placeholder makes the override obvious. ;; unset. Showing that value as placeholder makes the override obvious.
@ -264,7 +303,32 @@
(mf/use-fn (mf/use-fn
(mf/deps on-detach-token) (mf/deps on-detach-token)
(fn [token] (fn [token]
(on-detach-token token #{:stroke-width}))) (on-detach-token token #{:stroke-width-top :stroke-width-right
:stroke-width-bottom :stroke-width-left})))
on-detach-token-width-top
(mf/use-fn
(mf/deps on-detach-token)
(fn [token]
(on-detach-token token #{:stroke-width-top})))
on-detach-token-width-right
(mf/use-fn
(mf/deps on-detach-token)
(fn [token]
(on-detach-token token #{:stroke-width-right})))
on-detach-token-width-bottom
(mf/use-fn
(mf/deps on-detach-token)
(fn [token]
(on-detach-token token #{:stroke-width-bottom})))
on-detach-token-width-left
(mf/use-fn
(mf/deps on-detach-token)
(fn [token]
(on-detach-token token #{:stroke-width-left})))
stroke-caps-options stroke-caps-options
[{:id "none" :value "none" :label (tr "workspace.options.stroke-cap.none")} [{:id "none" :value "none" :label (tr "workspace.options.stroke-cap.none")}
@ -343,7 +407,7 @@
:attr :stroke-width :attr :stroke-width
:class (stl/css :numeric-input-wrapper) :class (stl/css :numeric-input-wrapper)
:property (tr "workspace.options.stroke-width") :property (tr "workspace.options.stroke-width")
:applied-token (get applied-tokens :stroke-width) :applied-token applied-token-width
:placeholder (if show-multiple-placeholder? :placeholder (if show-multiple-placeholder?
(tr "settings.multiple") (tr "settings.multiple")
"--") "--")
@ -420,46 +484,54 @@
(when per-side-expanded? (when per-side-expanded?
[:div {:class (stl/css :stroke-sides-options) [:div {:class (stl/css :stroke-sides-options)
:data-testid "stroke.per-side-options"} :data-testid "stroke.per-side-options"}
[:div {:class (stl/css :stroke-side-input) [:> numeric-input-wrapper* {:on-change on-width-top-change
:title (tr "workspace.options.stroke-width-top")} :on-detach on-detach-token-width-top
[:> icon* {:icon-id i/stroke-top :icon i/stroke-top
:size "s"}] :min 0
[:> deprecated-input/numeric-input* {:value (d/nilv (:stroke-width-top stroke) stroke-width) :on-focus on-focus
:min 0 :on-blur on-blur
:on-change on-width-top-change :attr :stroke-width-top
:on-focus on-focus :class (stl/css :numeric-input-wrapper)
:select-on-focus select-on-focus :property (tr "workspace.options.stroke-width-top")
:on-blur on-blur}]] :applied-token (get applied-tokens :stroke-width-top)
[:div {:class (stl/css :stroke-side-input) :nillable true
:title (tr "workspace.options.stroke-width-right")} :value (d/nilv (:stroke-width-top stroke) stroke-width)}]
[:> icon* {:icon-id i/stroke-right [:> numeric-input-wrapper* {:on-change on-width-right-change
:size "s"}] :on-detach on-detach-token-width-right
[:> deprecated-input/numeric-input* {:value (d/nilv (:stroke-width-right stroke) stroke-width) :icon i/stroke-right
:min 0 :min 0
:on-change on-width-right-change :on-focus on-focus
:on-focus on-focus :on-blur on-blur
:select-on-focus select-on-focus :attr :stroke-width-right
:on-blur on-blur}]] :class (stl/css :numeric-input-wrapper)
[:div {:class (stl/css :stroke-side-input) :property (tr "workspace.options.stroke-width-right")
:title (tr "workspace.options.stroke-width-bottom")} :applied-token (get applied-tokens :stroke-width-right)
[:> icon* {:icon-id i/stroke-bottom :nillable true
:size "s"}] :value (d/nilv (:stroke-width-right stroke) stroke-width)}]
[:> deprecated-input/numeric-input* {:value (d/nilv (:stroke-width-bottom stroke) stroke-width) [:> numeric-input-wrapper* {:on-change on-width-bottom-change
:min 0 :on-detach on-detach-token-width-bottom
:on-change on-width-bottom-change :icon i/stroke-bottom
:on-focus on-focus :min 0
:select-on-focus select-on-focus :on-focus on-focus
:on-blur on-blur}]] :on-blur on-blur
[:div {:class (stl/css :stroke-side-input) :attr :stroke-width-bottom
:title (tr "workspace.options.stroke-width-left")} :class (stl/css :numeric-input-wrapper)
[:> icon* {:icon-id i/stroke-left :property (tr "workspace.options.stroke-width-bottom")
:size "s"}] :applied-token (get applied-tokens :stroke-width-bottom)
[:> deprecated-input/numeric-input* {:value (d/nilv (:stroke-width-left stroke) stroke-width) :nillable true
:min 0 :value (d/nilv (:stroke-width-bottom stroke) stroke-width)}]
:on-change on-width-left-change [:> numeric-input-wrapper* {:on-change on-width-left-change
:on-focus on-focus :on-detach on-detach-token-width-left
:select-on-focus select-on-focus :icon i/stroke-left
:on-blur on-blur}]]]) :min 0
:on-focus on-focus
:on-blur on-blur
:attr :stroke-width-left
:class (stl/css :numeric-input-wrapper)
:property (tr "workspace.options.stroke-width-left")
:applied-token (get applied-tokens :stroke-width-left)
:nillable true
:value (d/nilv (:stroke-width-left stroke) stroke-width)}]])
;; Stroke Dash / Gap (only visible for dashed style) ;; Stroke Dash / Gap (only visible for dashed style)
(when (= stroke-style :dashed) (when (= stroke-style :dashed)

View File

@ -288,7 +288,14 @@
(dwta/update-shape-radius-for-corners value shape-ids attributes))) (dwta/update-shape-radius-for-corners value shape-ids attributes)))
(def shape-attribute-actions-map (def shape-attribute-actions-map
(let [stroke-width (partial generic-attribute-actions #{:stroke-width} "Stroke Width") (let [stroke-width (partial all-or-separate-actions {:attribute-labels {:stroke-width "Stroke Width"
:stroke-width-top "Top"
:stroke-width-right "Right"
:stroke-width-bottom "Bottom"
:stroke-width-left "Left"}
:hint (tr "workspace.tokens.stroke-width")
:on-update-shape-all dwta/update-stroke-width
:on-update-shape dwta/update-stroke-width-side})
font-size (partial generic-attribute-actions #{:font-size} "Font Size") font-size (partial generic-attribute-actions #{:font-size} "Font Size")
letter-spacing (partial generic-attribute-actions #{:letter-spacing} "Letter Spacing") letter-spacing (partial generic-attribute-actions #{:letter-spacing} "Letter Spacing")
font-family (partial generic-attribute-actions #{:font-family} "Font Family") font-family (partial generic-attribute-actions #{:font-family} "Font Family")
@ -337,7 +344,7 @@
(when (seq (border-radius context-data)) (when (seq (border-radius context-data))
[{:title "Border Radius" :submenu :border-radius}]) [{:title "Border Radius" :submenu :border-radius}])
[:separator] [:separator]
(stroke-width (assoc context-data :on-update-shape dwta/update-stroke-width)) (stroke-width context-data)
[:separator] [:separator]
(generic-attribute-actions #{:x} "X" (assoc context-data :on-update-shape dwta/update-shape-position :hint (tr "workspace.tokens.axis"))) (generic-attribute-actions #{:x} "X" (assoc context-data :on-update-shape dwta/update-shape-position :hint (tr "workspace.tokens.axis")))
(generic-attribute-actions #{:y} "Y" (assoc context-data :on-update-shape dwta/update-shape-position))) (generic-attribute-actions #{:y} "Y" (assoc context-data :on-update-shape dwta/update-shape-position)))

View File

@ -55,10 +55,19 @@
;; Color ;; Color
:fill "Fill" :fill "Fill"
:stroke-color "Stroke Color"}) :stroke-color "Stroke Color"
;; Stroke Width
:stroke-width-top "Top"
:stroke-width-right "Right"
:stroke-width-bottom "Bottom"
:stroke-width-left "Left"})
(def ^:private dimensions-dictionary (def ^:private dimensions-dictionary
{:stroke-width :stroke-width {:stroke-width-top :stroke-width
:stroke-width-right :stroke-width
:stroke-width-bottom :stroke-width
:stroke-width-left :stroke-width
:p1 :spacing :p1 :spacing
:p2 :spacing :p2 :spacing
:p3 :spacing :p3 :spacing

View File

@ -365,7 +365,7 @@
(ctht/apply-token-to-shape :frame1 "token-radius" [:r1 :r2 :r3 :r4] [:r1 :r2 :r3 :r4] 10) (ctht/apply-token-to-shape :frame1 "token-radius" [:r1 :r2 :r3 :r4] [:r1 :r2 :r3 :r4] 10)
(ctht/apply-token-to-shape :frame1 "token-rotation" [:rotation] [:rotation] 30) (ctht/apply-token-to-shape :frame1 "token-rotation" [:rotation] [:rotation] 30)
(ctht/apply-token-to-shape :frame1 "token-opacity" [:opacity] [:opacity] 0.7) (ctht/apply-token-to-shape :frame1 "token-opacity" [:opacity] [:opacity] 0.7)
(ctht/apply-token-to-shape :frame1 "token-stroke-width" [:stroke-width] [:stroke-width] 2) (ctht/apply-token-to-shape :frame1 "token-stroke-width" [:stroke-width-top :stroke-width-right :stroke-width-bottom :stroke-width-left] [:stroke-width] 2)
(ctht/apply-token-to-shape :frame1 "token-color" [:stroke-color] [:stroke-color] "#00ff00") (ctht/apply-token-to-shape :frame1 "token-color" [:stroke-color] [:stroke-color] "#00ff00")
(ctht/apply-token-to-shape :frame1 "token-color" [:fill] [:fill] "#00ff00") (ctht/apply-token-to-shape :frame1 "token-color" [:fill] [:fill] "#00ff00")
(ctht/apply-token-to-shape :frame1 "token-dimensions" [:width :height] [:width :height] 100) (ctht/apply-token-to-shape :frame1 "token-dimensions" [:width :height] [:width :height] 100)
@ -406,14 +406,17 @@
tokens-frame1' (:applied-tokens c-frame1')] tokens-frame1' (:applied-tokens c-frame1')]
;; ==== Check ;; ==== Check
(t/is (= (count tokens-frame1') 11)) (t/is (= (count tokens-frame1') 14))
(t/is (= (get tokens-frame1' :r1) "token-radius")) (t/is (= (get tokens-frame1' :r1) "token-radius"))
(t/is (= (get tokens-frame1' :r2) "token-radius")) (t/is (= (get tokens-frame1' :r2) "token-radius"))
(t/is (= (get tokens-frame1' :r3) "token-radius")) (t/is (= (get tokens-frame1' :r3) "token-radius"))
(t/is (= (get tokens-frame1' :r4) "token-radius")) (t/is (= (get tokens-frame1' :r4) "token-radius"))
(t/is (= (get tokens-frame1' :rotation) "token-rotation")) (t/is (= (get tokens-frame1' :rotation) "token-rotation"))
(t/is (= (get tokens-frame1' :opacity) "token-opacity")) (t/is (= (get tokens-frame1' :opacity) "token-opacity"))
(t/is (= (get tokens-frame1' :stroke-width) "token-stroke-width")) (t/is (= (get tokens-frame1' :stroke-width-top) "token-stroke-width"))
(t/is (= (get tokens-frame1' :stroke-width-right) "token-stroke-width"))
(t/is (= (get tokens-frame1' :stroke-width-bottom) "token-stroke-width"))
(t/is (= (get tokens-frame1' :stroke-width-left) "token-stroke-width"))
(t/is (= (get tokens-frame1' :stroke-color) "token-color")) (t/is (= (get tokens-frame1' :stroke-color) "token-color"))
(t/is (= (get tokens-frame1' :fill) "token-color")) (t/is (= (get tokens-frame1' :fill) "token-color"))
(t/is (= (get tokens-frame1' :width) "token-dimensions")) (t/is (= (get tokens-frame1' :width) "token-dimensions"))

View File

@ -508,9 +508,9 @@
rect-with-stroke (cths/get-shape file :rect-1) rect-with-stroke (cths/get-shape file :rect-1)
rect-without-stroke (cths/get-shape file :rect-2) rect-without-stroke (cths/get-shape file :rect-2)
events [(dwta/apply-token {:shape-ids [(:id rect-with-stroke) (:id rect-without-stroke)] events [(dwta/apply-token {:shape-ids [(:id rect-with-stroke) (:id rect-without-stroke)]
:attributes #{:stroke-width} :attributes #{:stroke-width-top :stroke-width-right :stroke-width-bottom :stroke-width-left}
:token (toht/get-token file "stroke-width.sm") :token (toht/get-token file "stroke-width.sm")
:on-update-shape dwta/update-stroke-width})]] :on-update-shape dwta/update-stroke-width-side})]]
(tohs/run-store-async (tohs/run-store-async
store done events store done events
(fn [new-state] (fn [new-state]
@ -518,12 +518,18 @@
token-target' (toht/get-token file' "stroke-width.sm") token-target' (toht/get-token file' "stroke-width.sm")
rect-with-stroke' (cths/get-shape file' :rect-1) rect-with-stroke' (cths/get-shape file' :rect-1)
rect-without-stroke' (cths/get-shape file' :rect-2)] rect-without-stroke' (cths/get-shape file' :rect-2)]
(t/testing "token got applied to rect with stroke and shape stroke got updated" (t/testing "token got applied to rect with stroke and shape stroke got updated"
(t/is (= (:stroke-width (:applied-tokens rect-with-stroke')) (:name token-target'))) (t/is (= (:stroke-width-top (:applied-tokens rect-with-stroke')) (:name token-target')))
(t/is (= (get-in rect-with-stroke' [:strokes 0 :stroke-width]) 10))) (t/is (= (:stroke-width-right (:applied-tokens rect-with-stroke')) (:name token-target')))
(t/testing "token got applied to rect without stroke and shape stroke got updated" (t/is (= (:stroke-width-bottom (:applied-tokens rect-with-stroke')) (:name token-target')))
(t/is (= (:stroke-width (:applied-tokens rect-without-stroke')) (:name token-target'))) (t/is (= (:stroke-width-left (:applied-tokens rect-with-stroke')) (:name token-target')))
(t/is (= (get-in rect-without-stroke' [:strokes 0 :stroke-width]) 10)))))))))) (t/is (= (get-in rect-with-stroke' [:strokes 0 :stroke-width]) 10)))
(t/testing "token got applied to rect without stroke and shape stroke got updated"
(t/is (= (:stroke-width-top (:applied-tokens rect-without-stroke')) (:name token-target')))
(t/is (= (:stroke-width-right (:applied-tokens rect-without-stroke')) (:name token-target')))
(t/is (= (:stroke-width-bottom (:applied-tokens rect-without-stroke')) (:name token-target')))
(t/is (= (:stroke-width-left (:applied-tokens rect-without-stroke')) (:name token-target')))
(t/is (= (get-in rect-without-stroke' [:strokes 0 :stroke-width]) 10))))))))))
(t/deftest test-apply-shadow (t/deftest test-apply-shadow
(t/testing "applies shadow token and updates the shapes with shadow" (t/testing "applies shadow token and updates the shapes with shadow"

View File

@ -165,7 +165,7 @@
{:case :stroke-width {:case :stroke-width
:token {:name "stroke-width-token" :type :stroke-width :value "2"} :token {:name "stroke-width-token" :type :stroke-width :value "2"}
:attribute :stroke-width :attribute :stroke-width-top
:shape :rect-shape} :shape :rect-shape}
{:case :text-case {:case :text-case

View File

@ -9686,6 +9686,10 @@ msgstr "Paddings"
msgid "workspace.tokens.radius" msgid "workspace.tokens.radius"
msgstr "Radius" msgstr "Radius"
#: src/app/main/ui/workspace/tokens/management/context_menu.cljs:287
msgid "workspace.tokens.stroke-width"
msgstr "Stroke Width"
#: src/app/main/ui/ds/controls/utilities/token_field.cljs:47, src/app/main/ui/workspace/tokens/management/token_pill.cljs:130 #: src/app/main/ui/ds/controls/utilities/token_field.cljs:47, src/app/main/ui/workspace/tokens/management/token_pill.cljs:130
msgid "workspace.tokens.ref-not-valid" msgid "workspace.tokens.ref-not-valid"
msgstr "Reference in {%s} is not valid or is not in any active set." msgstr "Reference in {%s} is not valid or is not in any active set."