Add delete and duplicate buttons to typography dialog (#8983)

*  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

* ♻️ 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`).

* ♻️ 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.

* ♻️ 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 <meobius123@gmail.com>
This commit is contained in:
Dream 2026-04-14 15:32:56 -04:00 committed by GitHub
parent 8cc05d9579
commit dfec9004bf
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 53 additions and 8 deletions

View File

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

View File

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

View File

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

View File

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