From c345c7cbaa20643e7a718b3a01efd58c44bea7d4 Mon Sep 17 00:00:00 2001 From: Eva Marco Date: Mon, 19 Oct 2026 15:35:44 +0200 Subject: [PATCH] :recycle: Use a DS icon button to remove imported SVG attributes (#12382) * :recycle: Use a DS icon button to remove imported SVG attributes Replace the raw remove button of each imported SVG attribute with the DS ghost icon button and the DS remove icon. The button had no title, so it gets a new "Remove attribute" label, which the DS tooltip shows. Drop the wrapper div that only held the button. Add a visual test that selects a group imported from SVG so the section shows. AI-assisted-by: claude-opus-5-5 * :recycle: Move imported SVG attributes styles to DS tokens The remove button is a DS icon button now, so .attr-actions and .attr-action-btn with their button placeholders go away. Inline the flex and ellipsis mixins, move spacing to DS tokens and logical properties, sizes to px2rem and the title color alias to its DS token. Use the DS body-small typography; its line-height is 1.3 instead of 1.4. Drop the line clamp rules of the attribute name: its later display: inline-block already overrode the -webkit-box they need. The refactor/ import stays only for %input-element on the value input, which moves with the inputs migration. AI-assisted-by: claude-opus-5-5 --- .../ui/visual-specs/workspace.spec.js | 26 +++++++++ .../sidebar/options/menus/svg_attrs.cljs | 11 ++-- .../sidebar/options/menus/svg_attrs.scss | 58 ++++++++----------- frontend/translations/en.po | 4 ++ frontend/translations/es.po | 4 ++ 5 files changed, 64 insertions(+), 39 deletions(-) diff --git a/frontend/playwright/ui/visual-specs/workspace.spec.js b/frontend/playwright/ui/visual-specs/workspace.spec.js index e67e97ce97..e3cf6f1358 100644 --- a/frontend/playwright/ui/visual-specs/workspace.spec.js +++ b/frontend/playwright/ui/visual-specs/workspace.spec.js @@ -261,3 +261,29 @@ test.describe("Selected colors", () => { }); }); }); + +test.describe("Imported SVG attributes", () => { + test("Shows the attributes of an imported SVG shape", async ({ page }) => { + const workspace = new WorkspacePage(page); + await workspace.setupEmptyFile(); + await workspace.mockRPC(/get\-file\?/, "workspace/get-file-9930.json"); + await workspace.goToWorkspace({ + fileId: "8f843b59-7fbb-81ce-8005-aa6d47ae3111", + pageId: "fb9798e7-a547-80ae-8005-9ffda4a13e2c", + }); + + // The fourth "workspace" board holds the imported SVG groups. + await workspace.clickToggableLayer("workspace", {}, 3); + await workspace.clickToggableLayer("Canvas"); + await workspace.clickLeafLayer("Rectangle 760 (Stroke)"); + + const section = workspace.rightSidebar.getByText("Imported SVG Attributes"); + await section.scrollIntoViewIfNeeded(); + await expect(section).toBeVisible(); + // The attributes are a small part of the sidebar: compare every pixel. + await expect(workspace.rightSidebar).toHaveScreenshot({ + maxDiffPixelRatio: 0, + threshold: 0, + }); + }); +}); diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/svg_attrs.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/menus/svg_attrs.cljs index ad07f27f6d..3dbd22eabb 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/svg_attrs.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/svg_attrs.cljs @@ -11,7 +11,8 @@ [app.main.data.workspace.shapes :as dwsh] [app.main.store :as st] [app.main.ui.components.title-bar :refer [title-bar*]] - [app.main.ui.icons :as deprecated-icon] + [app.main.ui.ds.buttons.icon-button :refer [icon-button*]] + [app.main.ui.ds.foundations.assets.icon :as i] [app.util.dom :as dom] [app.util.functions :as uf] [app.util.i18n :refer [tr]] @@ -48,10 +49,10 @@ [:div {:class (stl/css :attr-input)} [:input {:value @last-value :on-change handle-change}]] - [:div {:class (stl/css :attr-actions)} - [:button {:class (stl/css :attr-action-btn) - :on-click handle-delete} - deprecated-icon/remove-icon]]] + [:> icon-button* {:variant "ghost" + :aria-label (tr "workspace.sidebar.options.svg-attrs.remove") + :on-click handle-delete + :icon i/remove}]] [:div {:class (stl/css :attr-nested-content)} [:div {:class (stl/css :attr-title)} (str (d/name (last attr)))] diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/svg_attrs.scss b/frontend/src/app/main/ui/workspace/sidebar/options/menus/svg_attrs.scss index ed73954e38..949590ec94 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/svg_attrs.scss +++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/svg_attrs.scss @@ -4,77 +4,67 @@ // // Copyright (c) KALEIDOS SUBSIDIARY SL +// Only for %input-element: inputs move to the DS in their own plan. @use "refactor/common-refactor.scss" as deprecated; +@use "ds/_utils.scss" as *; +@use "ds/typography.scss" as *; .element-set { margin: 0; } .title-spacing-svg-attrs { - padding-left: deprecated.$s-2; + padding-inline-start: var(--sp-xxs); margin: 0; } .element-set-content { - @include deprecated.flex-column; - - margin: deprecated.$s-4 0 0 0; + display: flex; + flex-direction: column; + gap: var(--sp-xs); + margin-block-start: var(--sp-xs); } .attr-content { display: flex; - gap: deprecated.$s-4; + gap: var(--sp-xs); } .attr-name { - @include deprecated.body-small-typography; - @include deprecated.two-line-text-ellipsis; + @include use-typography("body-small"); - width: deprecated.$s-88; - margin: auto deprecated.$s-4; - margin-right: 0; display: inline-block; - color: var(--title-foreground-color); + overflow: hidden; + text-overflow: ellipsis; + inline-size: px2rem(88); + max-inline-size: 99%; + margin-block: auto; + margin-inline: var(--sp-xs) 0; + color: var(--color-foreground-secondary); } .attr-input { @extend %input-element; - @include deprecated.body-small-typography; + @include use-typography("body-small"); - width: deprecated.$s-124; -} - -.attr-actions { - display: flex; - gap: deprecated.$s-4; -} - -.attr-action-btn { - @extend %button-tertiary; - - width: deprecated.$s-28; - height: deprecated.$s-32; - - svg { - @extend %button-icon; - } + inline-size: px2rem(124); } .attr-nested-content { display: grid; - row-gap: deprecated.$s-4; + row-gap: var(--sp-xs); } .attr-title { - @include deprecated.body-small-typography; + @include use-typography("body-small"); - font-size: deprecated.$fs-10; + font-size: px2rem(10); text-transform: uppercase; - margin-inline-start: deprecated.$s-4; + margin-inline-start: var(--sp-xs); color: var(--color-foreground-primary); } .attr-row { display: flex; - gap: deprecated.$s-4; + gap: var(--sp-xs); } diff --git a/frontend/translations/en.po b/frontend/translations/en.po index f5cfa817f4..a735f09beb 100644 --- a/frontend/translations/en.po +++ b/frontend/translations/en.po @@ -8696,6 +8696,10 @@ msgstr "Shapes" msgid "workspace.sidebar.layers.texts" msgstr "Texts" +#: src/app/main/ui/workspace/sidebar/options/menus/svg_attrs.cljs:53 +msgid "workspace.sidebar.options.svg-attrs.remove" +msgstr "Remove attribute" + #: src/app/main/ui/inspect/attributes/svg.cljs:56, src/app/main/ui/workspace/sidebar/options/menus/svg_attrs.cljs:113 msgid "workspace.sidebar.options.svg-attrs.title" msgstr "Imported SVG Attributes" diff --git a/frontend/translations/es.po b/frontend/translations/es.po index 4ef52e1afe..6cc8b78b9d 100644 --- a/frontend/translations/es.po +++ b/frontend/translations/es.po @@ -8787,6 +8787,10 @@ msgstr "Formas" msgid "workspace.sidebar.layers.texts" msgstr "Textos" +#: src/app/main/ui/workspace/sidebar/options/menus/svg_attrs.cljs:53 +msgid "workspace.sidebar.options.svg-attrs.remove" +msgstr "Eliminar atributo" + #: src/app/main/ui/inspect/attributes/svg.cljs:56, src/app/main/ui/workspace/sidebar/options/menus/svg_attrs.cljs:113 msgid "workspace.sidebar.options.svg-attrs.title" msgstr "Atributos del SVG Importado"