mirror of
https://github.com/penpot/penpot.git
synced 2026-09-07 04:29:31 +00:00
🎉 Add selection size badge below bounding box (#9210)
* 🎉 Add selection size badge below bounding box Signed-off-by: bittoby <218712309+bittoby@users.noreply.github.com> * 💄 Address review comments Signed-off-by: bittoby <218712309+bittoby@users.noreply.github.com> * 💄 Move selection size badge text styles to SCSS class --------- Signed-off-by: bittoby <218712309+bittoby@users.noreply.github.com> Signed-off-by: BitToby <218712309+bittoby@users.noreply.github.com> Co-authored-by: Andrey Antukh <niwi@niwi.nz>
This commit is contained in:
parent
bb93928099
commit
6aeccb1208
@ -8,6 +8,8 @@
|
|||||||
|
|
||||||
### :sparkles: New features & Enhancements
|
### :sparkles: New features & Enhancements
|
||||||
|
|
||||||
|
- Show a read-only W × H size badge below the bounding box of the current selection so dimensions are visible directly on the canvas (initial implementation: always-on badge, single visual variant, no live-resize integration; remaining spec items follow in subsequent PRs) [Github #9205](https://github.com/penpot/penpot/issues/9205)
|
||||||
|
|
||||||
### :bug: Bugs fixed
|
### :bug: Bugs fixed
|
||||||
|
|
||||||
- Harden Nginx responses with standard security headers and hide upstream `X-Powered-By` headers
|
- Harden Nginx responses with standard security headers and hide upstream `X-Powered-By` headers
|
||||||
|
|||||||
@ -78,6 +78,32 @@ test("User draws a rect", async ({ page }) => {
|
|||||||
await expect(workspacePage.canvas).toHaveScreenshot();
|
await expect(workspacePage.canvas).toHaveScreenshot();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("Selection size badge appears on selection and hides on deselect", async ({
|
||||||
|
page,
|
||||||
|
}) => {
|
||||||
|
const workspacePage = new WasmWorkspacePage(page);
|
||||||
|
await workspacePage.setupEmptyFile();
|
||||||
|
await workspacePage.mockRPC(
|
||||||
|
/get\-file\?/,
|
||||||
|
"workspace/get-file-not-empty.json",
|
||||||
|
);
|
||||||
|
|
||||||
|
await workspacePage.goToWorkspace({
|
||||||
|
fileId: "6191cd35-bb1f-81f7-8004-7cc63d087374",
|
||||||
|
pageId: "6191cd35-bb1f-81f7-8004-7cc63d087375",
|
||||||
|
});
|
||||||
|
|
||||||
|
const badge = page.locator(".selection-size-badge");
|
||||||
|
|
||||||
|
await expect(badge).toHaveCount(0);
|
||||||
|
|
||||||
|
await workspacePage.clickLeafLayer("Rectangle");
|
||||||
|
await expect(badge).toBeVisible();
|
||||||
|
|
||||||
|
await workspacePage.page.keyboard.press("Escape");
|
||||||
|
await expect(badge).toHaveCount(0);
|
||||||
|
});
|
||||||
|
|
||||||
test("User makes a group", async ({ page }) => {
|
test("User makes a group", async ({ page }) => {
|
||||||
const workspacePage = new WasmWorkspacePage(page);
|
const workspacePage = new WasmWorkspacePage(page);
|
||||||
await workspacePage.setupEmptyFile();
|
await workspacePage.setupEmptyFile();
|
||||||
|
|||||||
@ -5,6 +5,7 @@
|
|||||||
;; Copyright (c) KALEIDOS INC
|
;; Copyright (c) KALEIDOS INC
|
||||||
|
|
||||||
(ns app.main.ui.measurements
|
(ns app.main.ui.measurements
|
||||||
|
(:require-macros [app.main.style :as stl])
|
||||||
(:require
|
(:require
|
||||||
[app.common.data :as d]
|
[app.common.data :as d]
|
||||||
[app.common.data.macros :as dm]
|
[app.common.data.macros :as dm]
|
||||||
@ -43,6 +44,13 @@
|
|||||||
(def distance-pill-height 16)
|
(def distance-pill-height 16)
|
||||||
(def distance-line-stroke 1)
|
(def distance-line-stroke 1)
|
||||||
|
|
||||||
|
(def ^:private ^:const selection-badge-bg-color "var(--color-accent-tertiary)")
|
||||||
|
(def ^:private ^:const selection-badge-height 16)
|
||||||
|
(def ^:private ^:const selection-badge-padding-x 6)
|
||||||
|
(def ^:private ^:const selection-badge-vertical-gap 8)
|
||||||
|
(def ^:private ^:const selection-badge-border-radius 2)
|
||||||
|
(def ^:private ^:const selection-badge-char-width 6.5)
|
||||||
|
|
||||||
|
|
||||||
;; ------------------------------------------------
|
;; ------------------------------------------------
|
||||||
;; HELPERS
|
;; HELPERS
|
||||||
@ -179,6 +187,35 @@
|
|||||||
:stroke hover-color
|
:stroke hover-color
|
||||||
:stroke-width selection-rect-width}}]]))
|
:stroke-width selection-rect-width}}]]))
|
||||||
|
|
||||||
|
(mf/defc selection-size-badge*
|
||||||
|
[{:keys [selrect zoom]}]
|
||||||
|
(let [{:keys [x y width height]} selrect
|
||||||
|
size-label (dm/str (fmt/format-number width) " x " (fmt/format-number height))
|
||||||
|
badge-height (/ selection-badge-height zoom)
|
||||||
|
padding-x (/ selection-badge-padding-x zoom)
|
||||||
|
gap (/ selection-badge-vertical-gap zoom)
|
||||||
|
radius (/ selection-badge-border-radius zoom)
|
||||||
|
text-width (* (count size-label) (/ selection-badge-char-width zoom))
|
||||||
|
badge-width (+ text-width (* 2 padding-x))
|
||||||
|
center-x (+ x (/ width 2))
|
||||||
|
badge-x (- center-x (/ badge-width 2))
|
||||||
|
badge-y (+ y height gap)
|
||||||
|
text-y (+ badge-y (/ badge-height 2))]
|
||||||
|
[:g.selection-size-badge {:pointer-events "none"}
|
||||||
|
[:rect {:x badge-x
|
||||||
|
:y badge-y
|
||||||
|
:width badge-width
|
||||||
|
:height badge-height
|
||||||
|
:rx radius
|
||||||
|
:ry radius
|
||||||
|
:style {:fill selection-badge-bg-color}}]
|
||||||
|
[:text {:class (stl/css :badge-text)
|
||||||
|
:x center-x
|
||||||
|
:y text-y
|
||||||
|
:text-anchor "middle"
|
||||||
|
:dominant-baseline "middle"}
|
||||||
|
size-label]]))
|
||||||
|
|
||||||
(mf/defc distance-display* [{:keys [from to zoom bounds]}]
|
(mf/defc distance-display* [{:keys [from to zoom bounds]}]
|
||||||
(let [fixed-x (if (gsh/fully-contained? from to)
|
(let [fixed-x (if (gsh/fully-contained? from to)
|
||||||
(+ (:x to) (/ (:width to) 2))
|
(+ (:x to) (/ (:width to) 2))
|
||||||
@ -244,6 +281,7 @@
|
|||||||
:bounds bounds
|
:bounds bounds
|
||||||
:zoom zoom}]
|
:zoom zoom}]
|
||||||
[:> size-display* {:selrect selected-selrect :zoom zoom}]
|
[:> size-display* {:selrect selected-selrect :zoom zoom}]
|
||||||
|
[:> selection-size-badge* {:selrect selected-selrect :zoom zoom}]
|
||||||
|
|
||||||
(if (or (not hover-shape) (not hover-selected-shape?))
|
(if (or (not hover-shape) (not hover-selected-shape?))
|
||||||
(when (and frame (not= uuid/zero (:id frame)))
|
(when (and frame (not= uuid/zero (:id frame)))
|
||||||
|
|||||||
13
frontend/src/app/main/ui/measurements.scss
Normal file
13
frontend/src/app/main/ui/measurements.scss
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
//
|
||||||
|
// Copyright (c) KALEIDOS INC
|
||||||
|
|
||||||
|
@use "refactor/common-refactor.scss" as deprecated;
|
||||||
|
|
||||||
|
.badge-text {
|
||||||
|
fill: var(--app-black);
|
||||||
|
font-size: calc(deprecated.$fs-12 / var(--zoom));
|
||||||
|
font-family: "worksans", "vazirmatn", sans-serif;
|
||||||
|
}
|
||||||
@ -500,6 +500,14 @@
|
|||||||
:zoom zoom
|
:zoom zoom
|
||||||
:modifiers modifiers}])
|
:modifiers modifiers}])
|
||||||
|
|
||||||
|
(when (and (seq selected-shapes)
|
||||||
|
(not transform)
|
||||||
|
(not text-editing?)
|
||||||
|
(not edition))
|
||||||
|
[:> msr/selection-size-badge*
|
||||||
|
{:selrect (gsh/shapes->rect selected-shapes)
|
||||||
|
:zoom zoom}])
|
||||||
|
|
||||||
(when show-measures?
|
(when show-measures?
|
||||||
[:> msr/measurement*
|
[:> msr/measurement*
|
||||||
{:bounds vbox
|
{:bounds vbox
|
||||||
|
|||||||
@ -653,6 +653,15 @@
|
|||||||
{:shape (get base-objects edition)
|
{:shape (get base-objects edition)
|
||||||
:zoom zoom}])
|
:zoom zoom}])
|
||||||
|
|
||||||
|
(when (and (seq selected-shapes)
|
||||||
|
(not transform)
|
||||||
|
(not text-editing?)
|
||||||
|
(not edition)
|
||||||
|
(not page-transition?))
|
||||||
|
[:> msr/selection-size-badge*
|
||||||
|
{:selrect (gsh/shapes->rect selected-shapes)
|
||||||
|
:zoom zoom}])
|
||||||
|
|
||||||
(when show-measures?
|
(when show-measures?
|
||||||
[:> msr/measurement*
|
[:> msr/measurement*
|
||||||
{:bounds vbox
|
{:bounds vbox
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user