🎉 Allow duplicating color and typography styles (#8449)

Add duplicate functionality for colors and typographies in the Assets
panel, matching the existing duplicate feature for components.

Changes:
- Add duplicate-color and duplicate-typography events in libraries
- Add Duplicate context menu option for colors
- Add Duplicate context menu option for typographies
- Update CHANGES.md

Closes #2912

Signed-off-by: mkdev11 <98430825+MkDev11@users.noreply.github.com>
This commit is contained in:
MkDev11 2026-02-26 01:13:34 -08:00 committed by GitHub
parent c27f874e74
commit e30c01db26
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 57 additions and 1 deletions

View File

@ -10,6 +10,7 @@
### :sparkles: New features & Enhancements
- Allow duplicating color and typography styles (by @MkDev11) [Github #2912](https://github.com/penpot/penpot/issues/2912)
- Add MCP server integration [Taiga #13112](https://tree.taiga.io/project/penpot/us/13112), [Taiga #13114](https://tree.taiga.io/project/penpot/us/13114)
- Add woff2 support on user uploaded fonts (by @Nivl) [Github #8248](https://github.com/penpot/penpot/pull/8248)
- Option to download custom fonts (by @dfelinto) [Github #8320](https://github.com/penpot/penpot/issues/8320)

View File

@ -221,6 +221,24 @@
(pcb/delete-color id))]
(rx/of (dch/commit-changes changes))))))
(defn duplicate-color
[file-id color-id]
(assert (uuid? file-id) "expected valid uuid for `file-id`")
(assert (uuid? color-id) "expected valid uuid for `color-id`")
(ptk/reify ::duplicate-color
ptk/WatchEvent
(watch [it state _]
(let [data (dsh/lookup-file-data state)
color (ctl/get-color data color-id)
new-color (-> color
(assoc :id (uuid/next))
(d/without-nils)
(ctc/check-library-color))
changes (-> (pcb/empty-changes it)
(pcb/add-color new-color))]
(rx/of (dch/commit-changes changes))))))
;; FIXME: this should be deleted
(defn add-media
[media]
@ -350,6 +368,23 @@
(pcb/delete-typography id))]
(rx/of (dch/commit-changes changes))))))
(defn duplicate-typography
[file-id typography-id]
(assert (uuid? file-id) "expected valid uuid for `file-id`")
(assert (uuid? typography-id) "expected valid uuid for `typography-id`")
(ptk/reify ::duplicate-typography
ptk/WatchEvent
(watch [it state _]
(let [data (dsh/lookup-file-data state)
typography (get-in data [:typographies typography-id])
new-typography (-> typography
(assoc :id (uuid/next))
(ctt/check-typography))
changes (-> (pcb/empty-changes it)
(pcb/add-typography new-typography))]
(rx/of (dch/commit-changes changes))))))
(defn- add-component2
"This is the second step of the component creation."
([selected]

View File

@ -93,6 +93,12 @@
(dwl/sync-file file-id file-id :colors color-id)
(dwu/commit-undo-transaction undo-id))))))
duplicate-color
(mf/use-fn
(mf/deps file-id color-id)
(fn []
(st/emit! (dwl/duplicate-color file-id color-id))))
rename-color-clicked
(mf/use-fn
(mf/deps read-only? local?)
@ -247,7 +253,10 @@
{:name (tr "workspace.assets.edit")
:id "assets-edit-color"
:handler edit-color-clicked})
(when-not (or multi-colors? multi-assets?)
{:name (tr "workspace.assets.duplicate")
:id "assets-duplicate-color"
:handler duplicate-color})
{:name (tr "workspace.assets.delete")
:id "assets-delete-color"
:handler delete-color}

View File

@ -377,6 +377,12 @@
(dwl/sync-file file-id file-id :typographies (:id @state))
(dwu/commit-undo-transaction undo-id))))))
handle-duplicate-typography
(mf/use-fn
(mf/deps file-id @state)
(fn []
(st/emit! (dwl/duplicate-typography file-id (:id @state)))))
editing-id (:edit-typography local-data)
renaming-id (:rename-typography local-data)
@ -440,6 +446,11 @@
:id "assets-edit-typography"
:handler handle-edit-typography-clicked})
(when-not (or multi-typographies? multi-assets?)
{:name (tr "workspace.assets.duplicate")
:id "assets-duplicate-typography"
:handler handle-duplicate-typography})
{:name (tr "workspace.assets.delete")
:id "assets-delete-typography"
:handler handle-delete-typography}