♻️ Use DS icons and buttons in the settings sidebar and email modal (#12541)

* ♻️ Use DS icons and buttons in the settings sidebar and email modal

- The settings sidebar back arrow and "Contact us" icon use the DS
  icons. The arrow keeps its place; the small DS icon draws 12px inside
  a 16px box, so the feedback icon sits 2px to the right and its margin
  shrinks to keep the label in place.
- The change email modal close button becomes a ghost DS icon button
  named "Close"; the class that places it goes on the tooltip wrapper.

The form submit buttons of the settings pages stay: they are the shared
forms submit button. A visual test covers the settings sidebar and the
change email modal.

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

* ♻️ Move settings sidebar and email modal styles to the DS

The settings sidebar no longer imports refactor/: its legacy mixins,
sizes and color aliases resolve to DS values and tokens, with logical
properties. Its z-index (1) has no DS token and keeps a TODO.

The change email modal does the same and keeps refactor/ only for the
modal placeholders (%modal-*), which move with the modals refactor. Its
legacy uppercase title becomes the DS headline-small typography, which
differs only in its size (12px instead of 11px): the modal grows 2px.
Two unused selectors are commented out with a TODO.

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

* 🔥 Remove unused styles from the change email modal

The SCSS refactor of the change email modal left rules commented out
with a TODO because the module does not use them, or because they target
an svg inside a DS icon that is the svg itself. CSS modules scope the
classes to this module and no other source uses them, so they go:
.select-title, .cancel-button. No visual change.

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

* ♻️ Tidy the settings sidebar and change email styles

The sidebar uses --z-index-panels instead of auto, the change email
submit button gets its own class instead of a bare button selector, and
the sidebar icons keep the DS stroke width (only the feedback icon line
gets thinner).

AI-assisted-by: claude-opus-5-5
This commit is contained in:
Eva Marco 2026-10-28 10:39:35 +01:00 committed by GitHub
parent b1018c77b7
commit 4d416bd3f2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 95 additions and 63 deletions

View File

@ -602,6 +602,32 @@ test.describe("Team pages controls", () => {
});
});
test.describe("Settings controls", () => {
const shot = { maxDiffPixelRatio: 0, threshold: 0 };
test("Sidebar and change email modal", async ({ page }) => {
await DashboardPage.mockConfigFlags(page, ["enable-user-feedback"]);
await page.goto("/?screen=settings-profile");
const sidebar = page.locator(
"[class*='settings_sidebar__dashboard-sidebar']",
);
await expect(page.getByText("Contact us")).toBeVisible();
await page.mouse.move(640, 700);
await expect(sidebar).toHaveScreenshot(shot);
await page.getByText("Dashboard", { exact: true }).hover();
await expect(sidebar).toHaveScreenshot(shot);
await page.getByText("Change email", { exact: true }).click();
const modal = page.locator("[class*='modal-container']");
await expect(modal).toBeVisible();
await page.mouse.move(10, 700);
await expect(modal).toHaveScreenshot(shot);
await modal.locator("[class*='modal-header'] button").hover();
await expect(modal).toHaveScreenshot(shot);
});
});
test.describe("Onboarding questions controls", () => {
const shot = { maxDiffPixelRatio: 0, threshold: 0 };

View File

@ -14,7 +14,8 @@
[app.main.refs :as refs]
[app.main.store :as st]
[app.main.ui.components.forms :as fm]
[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.main.ui.notifications.context-notification :refer [context-notification]]
[app.util.i18n :as i18n :refer [tr]]
[beicon.v2.core :as rx]
@ -88,8 +89,11 @@
[:h2 {:class (stl/css :modal-title)
:data-testid "change-email-title"}
(tr "modals.change-email.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)}
[:& context-notification
@ -114,7 +118,8 @@
[:div {:class (stl/css :action-buttons)
:data-testid "change-email-submit"}
[:> fm/submit-button*
{:label (tr "modals.change-email.submit")}]]]]]]))
{:label (tr "modals.change-email.submit")
:class (stl/css :submit-button)}]]]]]]))

View File

@ -4,7 +4,11 @@
//
// Copyright (c) KALEIDOS SUBSIDIARY SL
// refactor/ stays for the modal placeholders (%modal-*), which move with
// the modals refactor.
@use "refactor/common-refactor.scss" as deprecated;
@use "ds/_utils.scss" as *;
@use "ds/typography.scss" as *;
.modal-overlay {
@extend %modal-overlay-base;
@ -13,49 +17,45 @@
.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.uppercase-title-typography;
@include use-typography("headline-small");
color: var(--modal-title-foreground-color);
color: var(--color-foreground-primary);
}
// Tooltip wrapper of the close button: it places it in the corner.
.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 deprecated.body-small-typography;
@include use-typography("body-small");
gap: deprecated.$s-24;
margin-bottom: deprecated.$s-24;
display: flex;
flex-direction: column;
gap: var(--sp-xxl);
margin-block-end: var(--sp-xxl);
}
.fields-row {
@include deprecated.flex-column;
}
.select-title {
@include deprecated.body-small-typography;
color: var(--modal-title-foreground-color);
display: flex;
flex-direction: column;
gap: var(--sp-xs);
}
.action-buttons {
@extend %modal-action-btns;
button {
@extend %modal-accept-btn;
}
}
.cancel-button {
@extend %modal-cancel-btn;
.submit-button {
@extend %modal-accept-btn;
}

View File

@ -15,16 +15,11 @@
[app.main.router :as rt]
[app.main.store :as st]
[app.main.ui.dashboard.sidebar :refer [profile-section*]]
[app.main.ui.icons :as deprecated-icon]
[app.main.ui.ds.foundations.assets.icon :refer [icon*] :as i]
[app.util.i18n :as i18n :refer [tr]]
[app.util.keyboard :as kbd]
[rumext.v2 :as mf]))
(def ^:private arrow-icon
(deprecated-icon/icon-xref :arrow (stl/css :arrow-icon)))
(def ^:private feedback-icon
(deprecated-icon/icon-xref :feedback (stl/css :feedback-icon)))
;; FIXME: move to common
(def ^:private go-settings-profile
@ -82,7 +77,8 @@
[:div {:class (stl/css :sidebar-content-section)}
[:button {:class (stl/css :back-to-dashboard)
:on-click go-dashboard}
arrow-icon
[:> icon* {:icon-id i/arrow-left
:class (stl/css :arrow-icon)}]
[:span {:class (stl/css :back-text)} (tr "labels.dashboard")]]]
[:hr {:class (stl/css :sidebar-separator)}]
@ -143,7 +139,9 @@
[:li {:class (stl/css-case :current feedback?
:settings-item true)
:on-click go-settings-feedback}
feedback-icon
[:> icon* {:icon-id i/feedback
:size "s"
:class (stl/css :feedback-icon)}]
[:span {:class (stl/css :element-title)} (tr "labels.contact-us")]])]]]))
(mf/defc sidebar*

View File

@ -4,8 +4,11 @@
//
// Copyright (c) KALEIDOS SUBSIDIARY SL
@use "refactor/common-refactor.scss" as deprecated;
@use "ds/_borders.scss" as *;
@use "ds/_utils.scss" as *;
@use "ds/mixins.scss" as *;
@use "ds/typography.scss" as *;
@use "ds/z-index.scss" as *;
.dashboard-sidebar {
@include custom-scrollbar;
@ -14,24 +17,24 @@
grid-row: 1 / span 2;
display: grid;
grid-template-rows: 1fr auto;
height: 100%;
padding-block-start: deprecated.$s-16;
border-right: deprecated.$s-1 solid var(--panel-border-color);
z-index: deprecated.$z-index-1;
background-color: var(--panel-background-color);
block-size: 100%;
padding-block-start: var(--sp-l);
border-inline-end: $b-1 solid var(--color-background-quaternary);
z-index: var(--z-index-panels);
background-color: var(--color-background-primary);
}
.sidebar-content {
display: grid;
grid-template-rows: auto auto 1fr;
height: 100%;
block-size: 100%;
padding: 0;
overflow-y: auto;
}
.sidebar-separator {
border-color: transparent;
margin: deprecated.$s-12 deprecated.$s-16;
margin: var(--sp-m) var(--sp-l);
}
.sidebar-nav-settings {
@ -43,46 +46,48 @@
}
.settings-item {
--settings-foreground-color: var(--menu-foreground-color-rest);
--settings-foreground-color: var(--color-foreground-secondary);
--settings-background-color: transparent;
display: flex;
align-items: center;
padding: deprecated.$s-8 deprecated.$s-8 deprecated.$s-8 deprecated.$s-24;
padding: var(--sp-s) var(--sp-s) var(--sp-s) var(--sp-xxl);
color: var(--settings-foreground-color);
background-color: var(--settings-background-color);
cursor: pointer;
&:hover {
--settings-foreground-color: var(--sidebar-element-foreground-color-hover);
--settings-background-color: var(--sidebar-element-background-color-hover);
--settings-foreground-color: var(--color-accent-primary);
--settings-background-color: var(--color-background-secondary);
}
&.current {
--settings-foreground-color: var(--sidebar-element-foreground-color-selected);
--settings-background-color: var(--sidebar-element-background-color-selected);
--settings-foreground-color: var(--color-accent-primary);
--settings-background-color: var(--color-background-quaternary);
}
}
// The DS small icon draws 12px inside a 16px box: 4px less margin keeps
// the label where it was (the drawing sits 2px to the right).
.feedback-icon {
@extend %button-icon-small;
stroke: var(--settings-foreground-color);
margin-right: deprecated.$s-8;
flex-shrink: 0;
color: var(--settings-foreground-color);
margin-inline-end: var(--sp-xs);
}
.element-title {
@include deprecated.text-ellipsis;
@include deprecated.body-medium-typography;
@include text-ellipsis;
@include use-typography("body-medium");
}
.back-to-dashboard {
@include deprecated.button-style;
border: none;
background: none;
cursor: pointer;
display: flex;
align-items: center;
padding: deprecated.$s-12 deprecated.$s-16;
font-size: deprecated.$fs-14;
padding: var(--sp-m) var(--sp-l);
font-size: px2rem(14);
}
.back-text {
@ -90,9 +95,7 @@
}
.arrow-icon {
@extend %button-icon;
stroke: var(--icon-foreground);
transform: rotate(180deg);
margin-right: deprecated.$s-12;
flex-shrink: 0;
color: var(--color-foreground-secondary);
margin-inline-end: var(--sp-m);
}