🐛 Fix multiple selection on shapes with token applied to stroke-color (#9110)

*  Remove the need to navigate to page for deletion operation

* 🐛 Fix multiple selection with applied-tokens on stroke-color

* 🐛 Fix button position on page header

---------

Co-authored-by: Andrey Antukh <niwi@niwi.nz>
This commit is contained in:
Eva Marco 2026-04-24 09:47:44 +02:00 committed by GitHub
parent 20c6a28b52
commit 5a7ba7ee7e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 31 additions and 20 deletions

View File

@ -37,6 +37,7 @@
- Fix wrong `mapcat` call in `collect-main-shapes` - Fix wrong `mapcat` call in `collect-main-shapes`
- Fix stale accumulator in `get-children-in-instance` recursion - Fix stale accumulator in `get-children-in-instance` recursion
- Fix typo `:podition` in swap-shapes grid cell - Fix typo `:podition` in swap-shapes grid cell
- Fix multiple selection on shapes with token applied to stroke color
## 2.14.2 ## 2.14.2

View File

@ -29,9 +29,10 @@
.project-tree { .project-tree {
position: relative; position: relative;
flex-grow: 1; flex-grow: 1;
flex-shrink: 1;
min-width: 0;
height: deprecated.$s-32; height: deprecated.$s-32;
min-height: deprecated.$s-32; min-height: deprecated.$s-32;
max-width: calc(100% - deprecated.$s-64);
} }
.project-name, .project-name,

View File

@ -49,16 +49,16 @@
• :prop → the property type (:fill, :stroke, :shadow, etc.) • :prop → the property type (:fill, :stroke, :shadow, etc.)
• :shape-id → the UUID of the shape using this color • :shape-id → the UUID of the shape using this color
• :index → index of the color in the shape's fill/stroke list • :index → index of the color in the shape's fill/stroke list
Example of groups: Example of groups:
{ {
{:color \"#9f2929\", :opacity 0.3, :token-name \"asd2\" :has-token-applied true} {:color \"#9f2929\", :opacity 0.3, :token-name \"asd2\" :has-token-applied true}
[{:prop :fill, :shape-id #uuid \"d0231035-25c9-80d5-8006-eae4c3dff32e\", :index 0}] [{:prop :fill, :shape-id #uuid \"d0231035-25c9-80d5-8006-eae4c3dff32e\", :index 0}]
{:color \"#1b54b6\", :opacity 1} {:color \"#1b54b6\", :opacity 1}
[{:prop :fill, :shape-id #uuid \"aab34f9a-98c1-801a-8006-eae5e8236f1b\", :index 0}] [{:prop :fill, :shape-id #uuid \"aab34f9a-98c1-801a-8006-eae5e8236f1b\", :index 0}]
} }
This structure allows fast lookups of all shapes using the same visual color, This structure allows fast lookups of all shapes using the same visual color,
regardless of whether it comes from local fills, strokes or shadow-colors." regardless of whether it comes from local fills, strokes or shadow-colors."
@ -69,12 +69,10 @@
;; Unique color attribute maps ;; Unique color attribute maps
all-colors (distinct (mapv :attrs data)) all-colors (distinct (mapv :attrs data))
;; Split into: library colors, token colors, and plain colors ;; ;; Split into: library colors, token colors, and plain colors
library-colors (filterv :ref-id all-colors)
token-colors (filterv :token-name all-colors) token-colors (filterv :token-name all-colors)
colors (filterv #(and (nil? (:ref-id %)) library-colors (filterv (fn [c] (and (some? (:ref-id c)) (nil? (:token-name c)))) all-colors)
(not (:token-name %))) colors (filterv (fn [c] (and (nil? (:ref-id c)) (nil? (:token-name c)))) all-colors)]
all-colors)]
{:groups groups {:groups groups
:all-colors all-colors :all-colors all-colors
:colors colors :colors colors
@ -107,12 +105,11 @@
open? (deref open*) open? (deref open*)
has-colors? (or (some? (seq colors)) (some? (seq library-colors))) has-colors? (or (some? (seq colors)) (some? (seq library-colors)))
toggle-content (mf/use-fn #(swap! open* not)) toggle-content (mf/use-fn #(swap! open* not))
expand-lib-color (mf/use-state false) expand-lib-color (mf/use-state false)
expand-color (mf/use-state false) expand-color (mf/use-state false)
expand-token-color (mf/use-state false) expand-token-color (mf/use-state false)
;; TODO: Review if this is still necessary. ;; TODO: Review if this is still necessary.
prev-colors-ref (mf/use-ref nil) prev-colors-ref (mf/use-ref nil)

View File

@ -194,7 +194,9 @@
[:div {:class (stl/css-case :stroke-content true [:div {:class (stl/css-case :stroke-content true
:stroke-content-empty (not has-strokes?))} :stroke-content-empty (not has-strokes?))}
(cond (cond
(= :multiple strokes) (or (= :multiple (:stroke-color applied-tokens))
(= :multiple (:stroke-width applied-tokens))
(= :multiple strokes))
[:div {:class (stl/css :stroke-multiple)} [:div {:class (stl/css :stroke-multiple)}
[:div {:class (stl/css :stroke-multiple-label)} [:div {:class (stl/css :stroke-multiple-label)}
(tr "settings.multiple")] (tr "settings.multiple")]

View File

@ -71,12 +71,13 @@
[{:keys [active-tokens applied-token-name color on-swatch-click-token detach-token open-modal-from-token]}] [{:keys [active-tokens applied-token-name color on-swatch-click-token detach-token open-modal-from-token]}]
(let [;; `active-tokens` may be provided as a `delay` (lazy computation). (let [;; `active-tokens` may be provided as a `delay` (lazy computation).
;; In that case we must deref it (`@active-tokens`) to force evaluation ;; In that case we must deref it (`@active-tokens`) to force evaluation
;; and obtain the actual value. If its already realized (not a delay), ;; and obtain the actual value. If it's already realized (not a delay),
;; we just use it directly. ;; we just use it directly.
active-tokens (if (delay? active-tokens) active-tokens (if (delay? active-tokens)
@active-tokens @active-tokens
active-tokens) active-tokens)
active-color-tokens (:color active-tokens) active-color-tokens (:color active-tokens)
token (some #(when (= (:name %) applied-token-name) %) active-color-tokens) token (some #(when (= (:name %) applied-token-name) %) active-color-tokens)
@ -345,9 +346,14 @@
:dnd-over-top (= (:over dprops) :top) :dnd-over-top (= (:over dprops) :top)
:dnd-over-bot (= (:over dprops) :bot))] :dnd-over-bot (= (:over dprops) :bot))]
(when (= applied-token :multiple)
;; (js/console.trace "color-row*")
(prn "color-row*" index color applied-token))
(mf/with-effect [color prev-color disable-picker] (mf/with-effect [color prev-color disable-picker]
(when (and (not disable-picker) (not= prev-color color)) (when (and (not disable-picker) (not= prev-color color))
(modal/update-props! :colorpicker {:data (parse-color color)}))) (modal/update-props! :colorpicker {:data (parse-color color)})))
[:div {:class [class row-class]} [:div {:class [class row-class]}
;; Drag handler ;; Drag handler
(when (some? on-reorder) (when (some? on-reorder)

View File

@ -192,6 +192,8 @@
(when (some? on-reorder) (when (some? on-reorder)
[:> reorder-handler* {:ref dref}]) [:> reorder-handler* {:ref dref}])
(prn "stroke-row*" applied-tokens)
;; Stroke Color ;; Stroke Color
;; FIXME: memorize stroke color ;; FIXME: memorize stroke color
[:> color-row* {:color (ctc/stroke->color stroke) [:> color-row* {:color (ctc/stroke->color stroke)

View File

@ -89,11 +89,13 @@
on-delete on-delete
(mf/use-fn (mf/use-fn
(mf/deps id) (mf/deps id)
#(st/emit! (modal/show (fn [event]
{:type :confirm (dom/stop-propagation event)
:title (tr "modals.delete-page.title") (st/emit! (modal/show
:message (tr "modals.delete-page.body") {:type :confirm
:on-accept delete-fn}))) :title (tr "modals.delete-page.title")
:message (tr "modals.delete-page.body")
:on-accept delete-fn}))))
on-double-click on-double-click
(mf/use-fn (mf/use-fn