mirror of
https://github.com/penpot/penpot.git
synced 2026-10-29 05:50:35 +00:00
♻️ Use DS icon buttons in the viewer thumbnails panel (#12518)
* ♻️ Use DS icon buttons in the viewer thumbnails panel The expand, close and scroll buttons of the viewer thumbnails panel become ghost DS icon buttons. They had no accessible name; they are now labelled, and the expand button says whether the panel is expanded. The rotated legacy arrow gives way to the DS arrow icons. The thumbnails stay raw buttons, since they are list items. New keys: labels.expand and viewer.thumbnails.scroll-left/right (en, es). A visual test covers the panel collapsed, on hover and expanded. AI-assisted-by: claude-opus-5-5 * ♻️ Move viewer thumbnails panel styles off the deprecated styles Spacing, sizes, borders, typographies and color aliases move to DS tokens and logical properties, and the file no longer imports refactor/. The scroll buttons keep their 60px height through --button-height and still show only on hover; their tooltip wrappers take the grid cells. The DS body-small typography differs from the old one only in a more compact line-height, so the counter and the board names sit 1px higher. The panel z-index (10) has no DS token and keeps a TODO. AI-assisted-by: claude-opus-5-5
This commit is contained in:
parent
9911f82087
commit
ef17aea39e
@ -151,3 +151,42 @@ test("User opens Share modal", async ({ page }) => {
|
||||
).toBeVisible();
|
||||
await expect(viewerPage.page).toHaveScreenshot();
|
||||
});
|
||||
|
||||
test.describe("Thumbnails panel", () => {
|
||||
test("Shows the thumbnails panel collapsed and expanded", async ({
|
||||
page,
|
||||
}) => {
|
||||
const viewerPage = new ViewerPage(page);
|
||||
await viewerPage.setupLoggedInUser();
|
||||
await viewerPage.setupFileWithMultipleBoards();
|
||||
await viewerPage.goToViewer({
|
||||
fileId: "dd5cc0bb-91ff-81b9-8004-77df9cd3edb0",
|
||||
pageId: "dd5cc0bb-91ff-81b9-8004-77df9cd3edb3",
|
||||
});
|
||||
|
||||
await page.locator("#current-frame").click();
|
||||
const panel = page.locator("section").filter({ hasText: /boards/i });
|
||||
await expect(panel).toBeVisible();
|
||||
await page.mouse.move(640, 600);
|
||||
// Collapsed: the summary with its expand and close buttons.
|
||||
await expect(panel).toHaveScreenshot({
|
||||
maxDiffPixelRatio: 0,
|
||||
threshold: 0,
|
||||
});
|
||||
|
||||
// The scroll handlers only show on hover.
|
||||
await panel.locator("button").nth(3).hover();
|
||||
await expect(panel).toHaveScreenshot({
|
||||
maxDiffPixelRatio: 0,
|
||||
threshold: 0,
|
||||
});
|
||||
|
||||
await panel.locator("button").first().click();
|
||||
await page.mouse.move(640, 700);
|
||||
// Expanded: the expand arrow points up.
|
||||
await expect(panel).toHaveScreenshot({
|
||||
maxDiffPixelRatio: 0,
|
||||
threshold: 0,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -14,7 +14,8 @@
|
||||
[app.main.data.viewer :as dv]
|
||||
[app.main.render :as render]
|
||||
[app.main.store :as st]
|
||||
[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.object :as obj]
|
||||
@ -63,10 +64,18 @@
|
||||
[:div {:class (stl/css :thumbnails-list-expanded)} children]]
|
||||
|
||||
[:div {:class (stl/css :thumbnails-content)}
|
||||
[:button {:class (stl/css :left-scroll-handler)
|
||||
:on-click on-left-arrow-click} deprecated-icon/arrow]
|
||||
[:button {:class (stl/css :right-scroll-handler)
|
||||
:on-click on-right-arrow-click} deprecated-icon/arrow]
|
||||
[:> icon-button* {:variant "ghost"
|
||||
:class (stl/css :scroll-handler)
|
||||
:tooltip-class (stl/css :left-scroll-handler)
|
||||
:aria-label (tr "viewer.thumbnails.scroll-left")
|
||||
:icon i/arrow-left
|
||||
:on-click on-left-arrow-click}]
|
||||
[:> icon-button* {:variant "ghost"
|
||||
:class (stl/css :scroll-handler)
|
||||
:tooltip-class (stl/css :right-scroll-handler)
|
||||
:aria-label (tr "viewer.thumbnails.scroll-right")
|
||||
:icon i/arrow-right
|
||||
:on-click on-right-arrow-click}]
|
||||
|
||||
[:div {:class (stl/css :thumbnails-list)
|
||||
:ref container
|
||||
@ -76,15 +85,22 @@
|
||||
children]]])))
|
||||
|
||||
(mf/defc thumbnails-summary*
|
||||
[{:keys [on-toggle-expand on-close total]}]
|
||||
[{:keys [on-toggle-expand on-close total is-expanded]}]
|
||||
[:div {:class (stl/css :thumbnails-summary)}
|
||||
[:span {:class (stl/css :counter)}
|
||||
(tr "labels.num-of-frames" (i18n/c total))]
|
||||
[:span {:class (stl/css :actions)}
|
||||
[:button {:class (stl/css :expand-btn)
|
||||
:on-click on-toggle-expand} deprecated-icon/arrow]
|
||||
[:button {:class (stl/css :close-btn)
|
||||
:on-click on-close} deprecated-icon/close]]])
|
||||
[:> icon-button* {:variant "ghost"
|
||||
:aria-label (if is-expanded
|
||||
(tr "labels.collapse")
|
||||
(tr "labels.expand"))
|
||||
:aria-expanded (boolean is-expanded)
|
||||
:icon (if is-expanded i/arrow-up i/arrow-down)
|
||||
:on-click on-toggle-expand}]
|
||||
[:> icon-button* {:variant "ghost"
|
||||
:aria-label (tr "labels.close")
|
||||
:icon i/close
|
||||
:on-click on-close}]]])
|
||||
|
||||
(mf/defc thumbnail-item*
|
||||
{::mf/wrap [mf/memo
|
||||
@ -137,6 +153,7 @@
|
||||
|
||||
[:> thumbnails-summary* {:on-toggle-expand toggle-expand
|
||||
:on-close on-close
|
||||
:is-expanded expanded?
|
||||
:total (count frames)}]
|
||||
[:> thumbnails-content* {:is-expanded expanded?
|
||||
:total (count frames)}
|
||||
|
||||
@ -4,65 +4,52 @@
|
||||
//
|
||||
// Copyright (c) KALEIDOS SUBSIDIARY SL
|
||||
|
||||
@use "refactor/common-refactor.scss" as deprecated;
|
||||
@use "ds/_borders.scss" as *;
|
||||
@use "ds/_sizes.scss" as *;
|
||||
@use "ds/_utils.scss" as *;
|
||||
@use "ds/mixins.scss" as *;
|
||||
@use "ds/typography.scss" as *;
|
||||
|
||||
.viewer-thumbnails {
|
||||
background-color: var(--viewer-background-color);
|
||||
background-color: var(--color-background-secondary);
|
||||
grid-row: 1 / span 1;
|
||||
grid-column: 1 / span 1;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
z-index: deprecated.$z-index-10;
|
||||
|
||||
// TODO: no DS z-index token for 10; it keeps the panel above the
|
||||
// viewer content (z-index 2).
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.expanded {
|
||||
grid-row: 1 / span 2;
|
||||
|
||||
.expand-btn svg {
|
||||
transform: rotate(-90deg);
|
||||
}
|
||||
}
|
||||
|
||||
.thumbnails-summary {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
height: deprecated.$s-32;
|
||||
margin: deprecated.$s-24 deprecated.$s-24 0 deprecated.$s-24;
|
||||
block-size: $sz-32;
|
||||
margin: var(--sp-xxl) var(--sp-xxl) 0 var(--sp-xxl);
|
||||
}
|
||||
|
||||
.counter {
|
||||
@include deprecated.body-small-typography;
|
||||
@include use-typography("body-small");
|
||||
|
||||
color: var(--viewer-thumbnails-control-foreground-color);
|
||||
color: var(--color-foreground-secondary);
|
||||
}
|
||||
|
||||
.actions {
|
||||
@include deprecated.flex-row;
|
||||
|
||||
width: deprecated.$s-60;
|
||||
}
|
||||
|
||||
.expand-btn,
|
||||
.close-btn {
|
||||
@extend %button-tertiary;
|
||||
|
||||
height: deprecated.$s-32;
|
||||
width: deprecated.$s-28;
|
||||
|
||||
svg {
|
||||
@extend %button-icon;
|
||||
}
|
||||
}
|
||||
|
||||
.expand-btn svg {
|
||||
transform: rotate(90deg);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--sp-xs);
|
||||
}
|
||||
|
||||
.thumbnails-content {
|
||||
display: grid;
|
||||
grid-template-columns: deprecated.$s-40 auto deprecated.$s-40;
|
||||
grid-template-columns: $sz-40 auto $sz-40;
|
||||
grid-template-rows: auto;
|
||||
}
|
||||
|
||||
@ -74,36 +61,28 @@
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
// Tooltip wrappers of the scroll buttons: they take the grid cell.
|
||||
.right-scroll-handler,
|
||||
.left-scroll-handler {
|
||||
@extend %button-tertiary;
|
||||
@include deprecated.flex-center;
|
||||
|
||||
grid-column: 3 / span 1;
|
||||
grid-row: 1 / span 1;
|
||||
width: deprecated.$s-32;
|
||||
height: deprecated.$s-60;
|
||||
margin: auto 0;
|
||||
z-index: deprecated.$z-index-10;
|
||||
opacity: 0;
|
||||
|
||||
&:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
svg {
|
||||
@extend %button-icon;
|
||||
|
||||
stroke: var(--icon-foreground);
|
||||
}
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.left-scroll-handler {
|
||||
grid-column: 1 / span 1;
|
||||
grid-row: 1 / span 1;
|
||||
}
|
||||
|
||||
svg {
|
||||
transform: rotate(180deg);
|
||||
// The scroll buttons are as tall as a thumbnail row and only show on hover.
|
||||
.thumbnails-content .scroll-handler {
|
||||
--button-height: #{px2rem(60)};
|
||||
|
||||
opacity: 0;
|
||||
|
||||
&:hover,
|
||||
&:focus-visible {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@ -120,45 +99,49 @@
|
||||
position: relative;
|
||||
}
|
||||
|
||||
// A list item, not a DS button.
|
||||
.thumbnail-item {
|
||||
@include deprecated.button-style;
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: deprecated.$s-16;
|
||||
padding: var(--sp-l);
|
||||
border: none;
|
||||
background: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.thumbnail-preview {
|
||||
@include deprecated.flex-center;
|
||||
|
||||
width: deprecated.$s-132;
|
||||
min-height: deprecated.$s-132;
|
||||
height: deprecated.$s-132;
|
||||
padding: deprecated.$s-4;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
inline-size: px2rem(132);
|
||||
min-block-size: px2rem(132);
|
||||
block-size: px2rem(132);
|
||||
padding: var(--sp-xs);
|
||||
|
||||
// The board preview markup has no class of its own.
|
||||
svg {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
inline-size: 100%;
|
||||
block-size: 100%;
|
||||
}
|
||||
|
||||
&.selected {
|
||||
background-color: var(--viewer-thumbnail-background-color-selected);
|
||||
border-radius: deprecated.$br-8;
|
||||
background-color: var(--color-accent-primary-muted);
|
||||
border-radius: $br-8;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
border: deprecated.$s-1 solid var(--viewer-thumbnail-border-color);
|
||||
border-radius: deprecated.$br-8;
|
||||
border: $b-1 solid var(--color-accent-primary);
|
||||
border-radius: $br-8;
|
||||
}
|
||||
}
|
||||
|
||||
.thumbnail-info {
|
||||
@include deprecated.body-small-typography;
|
||||
@include deprecated.text-ellipsis;
|
||||
@include use-typography("body-small");
|
||||
@include text-ellipsis;
|
||||
|
||||
text-align: center;
|
||||
color: var(--viewer-thumbnails-control-foreground-color);
|
||||
padding: deprecated.$s-8 0;
|
||||
width: 100%;
|
||||
max-width: deprecated.$s-132;
|
||||
color: var(--color-foreground-secondary);
|
||||
padding: var(--sp-s) 0;
|
||||
inline-size: 100%;
|
||||
max-inline-size: px2rem(132);
|
||||
}
|
||||
|
||||
@ -2948,6 +2948,10 @@ msgstr "Error"
|
||||
msgid "labels.exit"
|
||||
msgstr "Exit"
|
||||
|
||||
#: src/app/main/ui/viewer/thumbnails.cljs:96
|
||||
msgid "labels.expand"
|
||||
msgstr "Expand"
|
||||
|
||||
#: src/app/main/ui/dashboard/team.cljs:782
|
||||
msgid "labels.expired-invitation"
|
||||
msgstr "Expired"
|
||||
@ -6127,6 +6131,14 @@ msgstr "Show interactions on click"
|
||||
msgid "viewer.header.sitemap"
|
||||
msgstr "Sitemap"
|
||||
|
||||
#: src/app/main/ui/viewer/thumbnails.cljs:70
|
||||
msgid "viewer.thumbnails.scroll-left"
|
||||
msgstr "Scroll left"
|
||||
|
||||
#: src/app/main/ui/viewer/thumbnails.cljs:76
|
||||
msgid "viewer.thumbnails.scroll-right"
|
||||
msgstr "Scroll right"
|
||||
|
||||
#: src/app/main/ui/workspace/webgl_unavailable_modal.cljs:76
|
||||
msgid "webgl.modals.webgl-unavailable.cta-dashboard"
|
||||
msgstr "Go to dashboard"
|
||||
|
||||
@ -2986,6 +2986,10 @@ msgstr "Error"
|
||||
msgid "labels.exit"
|
||||
msgstr "Salir"
|
||||
|
||||
#: src/app/main/ui/viewer/thumbnails.cljs:96
|
||||
msgid "labels.expand"
|
||||
msgstr "Expandir"
|
||||
|
||||
#: src/app/main/ui/dashboard/team.cljs:782
|
||||
msgid "labels.expired-invitation"
|
||||
msgstr "Expirada"
|
||||
@ -6208,6 +6212,14 @@ msgstr "Mostrar interacciones al hacer click"
|
||||
msgid "viewer.header.sitemap"
|
||||
msgstr "Mapa del sitio"
|
||||
|
||||
#: src/app/main/ui/viewer/thumbnails.cljs:70
|
||||
msgid "viewer.thumbnails.scroll-left"
|
||||
msgstr "Desplazar a la izquierda"
|
||||
|
||||
#: src/app/main/ui/viewer/thumbnails.cljs:76
|
||||
msgid "viewer.thumbnails.scroll-right"
|
||||
msgstr "Desplazar a la derecha"
|
||||
|
||||
#: src/app/main/ui/workspace/webgl_unavailable_modal.cljs:76
|
||||
msgid "webgl.modals.webgl-unavailable.cta-dashboard"
|
||||
msgstr "Ir al panel"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user