From f4f581ab74f8a4615f5ff45307ebadad9a1fbbf8 Mon Sep 17 00:00:00 2001 From: Eva Marco Date: Mon, 19 Oct 2026 10:50:32 +0200 Subject: [PATCH] :bug: Fix export scale dropdown clipped in Inspect (#12351) * :bug: Fix export scale dropdown clipped in Inspect The export selects in the Inspect tab used a dropdown class that always opened them upwards, overriding the select's own up/down choice. On elements with few properties the export section sits near the top of the panel, so the scale list (now eight options) went past the top of the scroll area and hid 0.5x. Keep only the dropdown width and let the select pick the direction. Closes #12346 AI-assisted-by: claude-opus-5-5 * :recycle: Move Inspect exports styles to DS tokens Replace the deprecated spacing and size variables, the flex mixins, the color aliases and the typography mixins with DS tokens, and use logical properties. The typographies switch to the closest DS ones: body-small for the suffix input (line-height 1.3 instead of 1.4) and headline-small for the export button (12px instead of 11px). The @extend placeholders still come from refactor/ and are left for a later migration. AI-assisted-by: claude-opus-5-5 * :recycle: Use DS buttons in Inspect exports Replace the add, remove and export buttons in the Inspect exports section with the DS icon-button and button, as the workspace export section does. Delete their now unused styles and the sizes import; the export button class only stretches the button and centers its label. AI-assisted-by: claude-opus-5-5 * :bug: Fix add export button lookup in the Inspect exports e2e test The add export button in Inspect is a DS icon button now and lost its .add-export class, so the test timed out waiting for it. Find it by its role and accessible name instead. AI-assisted-by: claude-opus-5-5 --- .../ui/specs/viewer-inspect-exports.spec.js | 5 +- frontend/src/app/main/ui/inspect/exports.cljs | 37 +++++----- frontend/src/app/main/ui/inspect/exports.scss | 73 ++++++------------- 3 files changed, 45 insertions(+), 70 deletions(-) diff --git a/frontend/playwright/ui/specs/viewer-inspect-exports.spec.js b/frontend/playwright/ui/specs/viewer-inspect-exports.spec.js index 3e99476fe5..b1da71a01f 100644 --- a/frontend/playwright/ui/specs/viewer-inspect-exports.spec.js +++ b/frontend/playwright/ui/specs/viewer-inspect-exports.spec.js @@ -23,11 +23,8 @@ test("[View mode] Export presets are preserved when navigating between boards in // Enter inspect (code) mode await viewer.showCode(); - // Wait for the inspect panel to load - await page.waitForSelector(".main_ui_inspect_exports__add-export"); - // Add an export preset via the "+" button in the Export section - const addExportButton = page.locator(".main_ui_inspect_exports__add-export"); + const addExportButton = page.getByRole("button", { name: "Add export" }); await addExportButton.click(); // Verify the "Export 1 element" button appears, confirming the preset was added diff --git a/frontend/src/app/main/ui/inspect/exports.cljs b/frontend/src/app/main/ui/inspect/exports.cljs index dab7869948..c70e37ff05 100644 --- a/frontend/src/app/main/ui/inspect/exports.cljs +++ b/frontend/src/app/main/ui/inspect/exports.cljs @@ -14,7 +14,9 @@ [app.main.store :as st] [app.main.ui.components.select :refer [select]] [app.main.ui.components.title-bar :refer [title-bar*]] - [app.main.ui.icons :as deprecated-icon] + [app.main.ui.ds.buttons.button :refer [button*]] + [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.i18n :refer [tr c]] [app.util.keyboard :as kbd] @@ -161,17 +163,19 @@ [:> title-bar* {:collapsable false :title (tr "workspace.options.export") :class (stl/css :title-spacing-export-viewer)} - [:button {:class (stl/css :add-export) - :on-click add-export} deprecated-icon/add]]] + [:> icon-button* {:variant "ghost" + :aria-label (tr "workspace.options.export.add-export") + :on-click add-export + :icon i/add}]]] (cond (= :multiple exports) [:div {:class (stl/css :multiple-exports)} [:div {:class (stl/css :label)} (tr "settings.multiple")] [:div {:class (stl/css :actions)} - [:button {:class (stl/css :action-btn) - :on-click ()} - deprecated-icon/remove-icon]]] + [:> icon-button* {:variant "ghost" + :aria-label (tr "workspace.options.export.remove-export") + :icon i/remove}]]] (seq @exports) [:div {:class (stl/css :element-set-content)} @@ -183,14 +187,14 @@ [:& select {:default-value (d/name (:type export)) :options format-options - :dropdown-class (stl/css :dropdown-upwards) + :dropdown-class (stl/css :dropdown) :on-change (partial on-type-change index)}]] (when (scale-enabled? export) [:div {:class (stl/css :size-select)} [:& select {:default-value (str (:scale export)) :options size-options - :dropdown-class (stl/css :dropdown-upwards) + :dropdown-class (stl/css :dropdown) :on-change (partial on-scale-change index)}]]) [:label {:class (stl/css :suffix-input) :for "suffix-export-input"} @@ -203,16 +207,15 @@ :on-change on-suffix-change :on-key-down manage-key-down}]]] - [:button {:class (stl/css :action-btn) - :on-click (partial delete-export index)} - deprecated-icon/remove-icon]])]) + [:> icon-button* {:variant "ghost" + :aria-label (tr "workspace.options.export.remove-export") + :on-click (partial delete-export index) + :icon i/remove}]])]) (when (or (= :multiple exports) (seq @exports)) - [:button - {:on-click (when-not in-progress? on-download) - :class (stl/css-case - :export-btn true - :btn-disabled in-progress?) - :disabled in-progress?} + [:> button* {:variant "secondary" + :class (stl/css :export-btn) + :on-click (when-not in-progress? on-download) + :disabled in-progress?} (if in-progress? (tr "workspace.options.exporting-object") (tr "workspace.options.export-object" (c (count shapes))))])])) diff --git a/frontend/src/app/main/ui/inspect/exports.scss b/frontend/src/app/main/ui/inspect/exports.scss index 1feb282b4c..67345837ac 100644 --- a/frontend/src/app/main/ui/inspect/exports.scss +++ b/frontend/src/app/main/ui/inspect/exports.scss @@ -5,9 +5,11 @@ // Copyright (c) KALEIDOS SUBSIDIARY SL @use "refactor/common-refactor.scss" as deprecated; +@use "ds/typography.scss" as *; +@use "ds/_utils.scss" as *; .element-set { - padding-bottom: deprecated.$s-16; + padding-block-end: var(--sp-l); margin: 0; } @@ -17,33 +19,22 @@ .title-spacing-export-viewer { margin: 0; - color: var(--entry-foreground-color-hover); - margin-inline-start: calc(-1 * deprecated.$s-8); - width: calc(100% + deprecated.$s-8); -} - -.add-export { - @extend %button-tertiary; - - height: deprecated.$s-32; - width: deprecated.$s-28; - - svg { - @extend %button-icon; - - stroke: var(--icon-foreground); - } + color: var(--color-foreground-primary); + margin-inline-start: calc(-1 * var(--sp-s)); + inline-size: calc(100% + var(--sp-s)); } .element-set-content { - @include deprecated.flex-column; - - margin-bottom: deprecated.$s-4; + display: flex; + flex-direction: column; + gap: var(--sp-xs); + margin-block-end: var(--sp-xs); } .multiple-exports { - @include deprecated.flex-row; - + display: flex; + align-items: center; + gap: var(--sp-xs); grid-column: 1 / span 9; } @@ -52,24 +43,15 @@ } .actions { - @include deprecated.flex-row; + display: flex; + align-items: center; + gap: var(--sp-xs); } .element-group { display: grid; grid-template-columns: repeat(9, 1fr); - column-gap: deprecated.$s-4; - - .action-btn { - @extend %button-tertiary; - - height: deprecated.$s-32; - width: deprecated.$s-28; - - svg { - @extend %button-icon; - } - } + column-gap: var(--sp-xs); } .input-wrapper { @@ -82,10 +64,8 @@ grid-column: span 3; padding: 0; - .dropdown-upwards { - bottom: deprecated.$s-36; - width: deprecated.$s-80; - top: unset; + .dropdown { + inline-size: px2rem(80); } } @@ -93,24 +73,19 @@ grid-column: span 2; padding: 0; - .dropdown-upwards { - bottom: deprecated.$s-36; - top: unset; - width: deprecated.$s-80; + .dropdown { + inline-size: px2rem(80); } } .suffix-input { @extend %input-element; - @include deprecated.body-small-typography; + @include use-typography("body-small"); grid-column: span 3; } .export-btn { - @extend %button-secondary; - @include deprecated.uppercase-title-typography; - - height: deprecated.$s-32; - width: 100%; + justify-content: center; + inline-size: 100%; }