♻️ Use a DS icon button to close the nudge amount modal (#12439)

* ♻️ Use a DS icon button to close the nudge amount modal

The close button of the nudge amount modal (main menu, Preferences) was a
raw button with a deprecated icon and no accessible name. Replace it with
a DS ghost icon button labeled "Close", shown in its DS tooltip. The class
that places it in the corner goes on the tooltip wrapper, so the tooltip
anchors to the button. The numeric inputs stay for the inputs group.

Add a visual test that opens the modal from the main menu.

AI-assisted-by: claude-opus-5-5

* ♻️ Move nudge modal styles off the deprecated styles

The close button is a DS icon button, so its placeholder goes away; it is
now 32px wide instead of 28px, and sits 4px from the edge instead of 6px
so the icon stays in the same place. Spacing, sizes and the color aliases
move to DS tokens and logical properties, the flex mixin is inlined, and
the label rule targets its class instead of the label element.

The title matches the DS headline-medium typography exactly. The content
and labels use body-large and the wrapper body-small, whose line-heights
differ by 0.1 from the legacy ones; the labels keep their 1.5 override,
so nothing visible changes.

refactor/ stays only for the shared modal and labeled input placeholders.

AI-assisted-by: claude-opus-5-5
This commit is contained in:
Eva Marco 2026-10-19 14:28:03 +02:00 committed by GitHub
parent 8787937b7c
commit 18ca25518e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 47 additions and 18 deletions

View File

@ -219,6 +219,25 @@ test.describe("Palette", () => {
});
});
test.describe("Nudge modal", () => {
test("Shows the nudge amount modal", async ({ page }) => {
const workspace = new WorkspacePage(page);
await workspace.setupEmptyFile();
await workspace.goToWorkspace();
await page.getByRole("button", { name: "Main menu" }).click();
await page.locator("#file-menu-preferences").click();
await page.locator("#file-menu-nudge").click();
await expect(page.getByText("Nudge amount")).toBeVisible();
await page.mouse.move(0, 0);
await expect(workspace.page).toHaveScreenshot("nudge-modal.png", {
maxDiffPixelRatio: 0,
threshold: 0,
});
});
});
test.describe("Selected colors", () => {
test("Shows the more colors button", async ({ page }) => {
const workspace = new WorkspacePage(page);

View File

@ -12,7 +12,8 @@
[app.main.refs :as refs]
[app.main.store :as st]
[app.main.ui.components.numeric-input :as deprecated-input]
[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.i18n :as i18n :refer [tr]]
[app.util.keyboard :as k]
@ -44,8 +45,11 @@
[:div {:class (stl/css :modal-container)}
[:div {:class (stl/css :modal-header)}
[:h2 {:class (stl/css :modal-title)} (tr "modals.nudge-title")]
[:button {:class (stl/css :modal-close-btn)
:on-click modal/hide!} deprecated-icon/close]]
[:> icon-button* {:variant "ghost"
:tooltip-class (stl/css :modal-close-btn)
:aria-label (tr "labels.close")
:icon i/close
:on-click modal/hide!}]]
[:div {:class (stl/css :modal-content)}
[:div {:class (stl/css :input-wrapper)}
[:label {:class (stl/css :modal-msg)

View File

@ -4,7 +4,11 @@
//
// Copyright (c) KALEIDOS SUBSIDIARY SL
// Only for the shared modal and labeled input placeholders, which move to
// the DS with the modals and the inputs.
@use "refactor/common-refactor.scss" as deprecated;
@use "ds/_utils.scss" as *;
@use "ds/typography.scss" as *;
.modal-overlay {
@extend %modal-overlay-base;
@ -13,45 +17,47 @@
.modal-container {
@extend %modal-container-base;
min-width: deprecated.$s-408;
min-inline-size: px2rem(408);
}
.modal-header {
margin-bottom: deprecated.$s-24;
margin-block-end: var(--sp-xxl);
}
.modal-title {
@include deprecated.headline-medium-typography;
@include use-typography("headline-medium");
color: var(--modal-title-foreground-color);
color: var(--color-foreground-primary);
}
.modal-close-btn {
@extend %modal-close-btn-base;
position: absolute;
inset-block-start: var(--sp-s);
inset-inline-end: var(--sp-xs);
}
.modal-content {
@include deprecated.flex-column;
@include use-typography("body-large");
gap: deprecated.$s-24;
@include deprecated.body-large-typography;
margin-bottom: deprecated.$s-24;
display: flex;
flex-direction: column;
gap: var(--sp-xxl);
margin-block-end: var(--sp-xxl);
}
.input-wrapper {
@extend %input-with-label;
@include deprecated.body-small-typography;
@include use-typography("body-small");
label {
// Nested so it wins over the label rule of %input-with-label.
.modal-msg {
text-transform: none;
}
}
.modal-msg {
@include deprecated.body-large-typography;
@include use-typography("body-large");
color: var(--modal-text-foreground-color);
color: var(--color-foreground-secondary);
line-height: 1.5;
}