From dfec9004bf3132b93b9a53dcefa07e1962c57495 Mon Sep 17 00:00:00 2001 From: Dream <42954461+eureka0928@users.noreply.github.com> Date: Tue, 14 Apr 2026 15:32:56 -0400 Subject: [PATCH] :sparkles: Add delete and duplicate buttons to typography dialog (#8983) * :sparkles: Add delete and duplicate buttons to typography dialog Add delete and duplicate action buttons to the expanded typography editing panel, allowing users to quickly manage typographies without needing to close the panel and use the context menu. Fixes #5270 * :recycle: Use DS icon-button for typography dialog actions Address review feedback: replace raw `:button`/`:div` elements and deprecated-icon usage with the design system `icon-button*` and non-deprecated icons (`i/add`, `i/delete`, `i/tick`). * :recycle: Only show typography delete/duplicate buttons in assets sidebar `typography-entry` is reused from the right sidebar text options panel, where the delete and duplicate actions don't make sense. Add an `is-asset?` opt-in prop and gate the `on-delete`/`on-duplicate` handlers behind it, so the buttons only appear when the entry is rendered from the assets sidebar. * :recycle: Move typography delete/duplicate handlers next to their use site Refine the previous opt-in: instead of plumbing on-delete/on-duplicate function props through typography-entry, build them directly inside typography-advanced-options where they're actually rendered. The component now takes :file-id and :is-asset? and gates the action buttons on a single `show-actions?` flag. --------- Signed-off-by: eureka0928 --- CHANGES.md | 1 + .../sidebar/assets/typographies.cljs | 3 +- .../sidebar/options/menus/typography.cljs | 51 ++++++++++++++++--- .../sidebar/options/menus/typography.scss | 6 +++ 4 files changed, 53 insertions(+), 8 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 3cc7a1ae0f..f7ba9d16c0 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -72,6 +72,7 @@ - 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) - Persist asset search query and section filter when switching sidebar tabs (by @eureka0928) [Github #2913](https://github.com/penpot/penpot/issues/2913) +- Add delete and duplicate buttons to typography dialog (by @eureka0928) [Github #5270](https://github.com/penpot/penpot/issues/5270) ### :bug: Bugs fixed diff --git a/frontend/src/app/main/ui/workspace/sidebar/assets/typographies.cljs b/frontend/src/app/main/ui/workspace/sidebar/assets/typographies.cljs index d9665d4bba..082fecb996 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/assets/typographies.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/assets/typographies.cljs @@ -125,7 +125,8 @@ :editing? editing? :renaming? renaming? :focus-name? rename? - :external-open* open*}] + :external-open* open* + :is-asset? true}] (when ^boolean dragging? [:div {:class (stl/css :dragging)}])])) diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/typography.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/menus/typography.cljs index 940682be89..90124b22aa 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/typography.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/typography.cljs @@ -16,6 +16,8 @@ [app.main.data.common :as dcm] [app.main.data.fonts :as fts] [app.main.data.shortcuts :as dsc] + [app.main.data.workspace.libraries :as dwl] + [app.main.data.workspace.undo :as dwu] [app.main.features :as features] [app.main.fonts :as fonts] [app.main.refs :as refs] @@ -26,6 +28,7 @@ [app.main.ui.components.search-bar :refer [search-bar*]] [app.main.ui.components.select :refer [select]] [app.main.ui.context :as ctx] + [app.main.ui.ds.buttons.icon-button :refer [icon-button*]] [app.main.ui.ds.foundations.assets.icon :as i] [app.main.ui.icons :as deprecated-icon] [app.util.dom :as dom] @@ -464,9 +467,29 @@ (mf/defc typography-advanced-options {::mf/wrap [mf/memo]} - [{:keys [visible? typography editable? name-input-ref on-close on-change on-name-blur local? navigate-to-library on-key-down]}] - (let [ref (mf/use-ref nil) - font-data (fonts/get-font-data (:font-id typography))] + [{:keys [visible? typography editable? name-input-ref on-close on-change on-name-blur + local? navigate-to-library on-key-down file-id is-asset?]}] + (let [ref (mf/use-ref nil) + font-data (fonts/get-font-data (:font-id typography)) + typography-id (:id typography) + show-actions? (and is-asset? editable?) + + on-delete + (mf/use-fn + (mf/deps typography-id file-id on-close) + (fn [] + (on-close) + (let [undo-id (js/Symbol)] + (st/emit! (dwu/start-undo-transaction undo-id) + (dwl/delete-typography typography-id) + (dwl/sync-file file-id file-id :typographies typography-id) + (dwu/commit-undo-transaction undo-id))))) + + on-duplicate + (mf/use-fn + (mf/deps file-id typography-id) + (fn [] + (st/emit! (dwl/duplicate-typography file-id typography-id))))] (fonts/ensure-loaded! (:font-id typography)) (mf/use-effect @@ -498,9 +521,21 @@ :on-key-down on-key-down :on-blur on-name-blur}] - [:div {:class (stl/css :action-btn) - :on-click on-close} - deprecated-icon/tick]] + [:div {:class (stl/css :action-btns)} + (when show-actions? + [:* + [:> icon-button* {:variant "ghost" + :aria-label (tr "workspace.assets.duplicate") + :on-click on-duplicate + :icon i/add}] + [:> icon-button* {:variant "ghost" + :aria-label (tr "workspace.assets.delete") + :on-click on-delete + :icon i/delete}]]) + [:> icon-button* {:variant "ghost" + :aria-label (tr "labels.close") + :on-click on-close + :icon i/tick}]]] [:& text-options {:values typography :on-change on-change @@ -551,7 +586,7 @@ (mf/defc typography-entry {::mf/wrap-props false} - [{:keys [file-id typography local? selected? on-click on-change on-detach on-context-menu editing? renaming? focus-name? external-open*]}] + [{:keys [file-id typography local? selected? on-click on-change on-detach on-context-menu editing? renaming? focus-name? external-open* is-asset?]}] (let [name-input-ref (mf/use-ref) read-only? (mf/use-ctx ctx/workspace-read-only?) editable? (and local? (not read-only?)) @@ -667,5 +702,7 @@ :on-change on-change :on-name-blur on-name-blur :on-key-down on-key-down + :file-id file-id + :is-asset? is-asset? :local? local? :navigate-to-library navigate-to-library}]])) diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/typography.scss b/frontend/src/app/main/ui/workspace/sidebar/options/menus/typography.scss index a9f91e206a..29213fd2ac 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/typography.scss +++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/typography.scss @@ -146,6 +146,12 @@ } } + .action-btns { + display: flex; + align-items: center; + gap: deprecated.$s-2; + } + &:focus-within { border: deprecated.$s-1 solid var(--input-border-color-active);