diff --git a/frontend/playwright/ui/visual-specs/visual-viewer.spec.js b/frontend/playwright/ui/visual-specs/visual-viewer.spec.js index 8361c263fb..9fb96ad4b3 100644 --- a/frontend/playwright/ui/visual-specs/visual-viewer.spec.js +++ b/frontend/playwright/ui/visual-specs/visual-viewer.spec.js @@ -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, + }); + }); +}); diff --git a/frontend/src/app/main/ui/viewer/thumbnails.cljs b/frontend/src/app/main/ui/viewer/thumbnails.cljs index d7af5b5d41..d23c5009b8 100644 --- a/frontend/src/app/main/ui/viewer/thumbnails.cljs +++ b/frontend/src/app/main/ui/viewer/thumbnails.cljs @@ -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)} diff --git a/frontend/src/app/main/ui/viewer/thumbnails.scss b/frontend/src/app/main/ui/viewer/thumbnails.scss index 63dc586a67..fdea0a3443 100644 --- a/frontend/src/app/main/ui/viewer/thumbnails.scss +++ b/frontend/src/app/main/ui/viewer/thumbnails.scss @@ -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); } diff --git a/frontend/translations/en.po b/frontend/translations/en.po index 4d87a2c487..577cc740a1 100644 --- a/frontend/translations/en.po +++ b/frontend/translations/en.po @@ -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" diff --git a/frontend/translations/es.po b/frontend/translations/es.po index d40ca22260..434c88d4ba 100644 --- a/frontend/translations/es.po +++ b/frontend/translations/es.po @@ -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"