Selection area on rules

This commit is contained in:
alonso.torres 2022-02-02 18:08:47 +01:00
parent 5cac5eb26b
commit 1dee767762
10 changed files with 148 additions and 54 deletions

View file

@ -18,7 +18,7 @@
- Improve file menu by adding semantically groups [Github #1203](https://github.com/penpot/penpot/issues/1203) - Improve file menu by adding semantically groups [Github #1203](https://github.com/penpot/penpot/issues/1203)
- Add update components in bulk option in context menu [Taiga #1975](https://tree.taiga.io/project/penpot/us/1975) - Add update components in bulk option in context menu [Taiga #1975](https://tree.taiga.io/project/penpot/us/1975)
- Create first E2E tests [Taiga #2608](https://tree.taiga.io/project/penpot/task/2608), [Taiga #2608](https://tree.taiga.io/project/penpot/task/2608) - Create first E2E tests [Taiga #2608](https://tree.taiga.io/project/penpot/task/2608), [Taiga #2608](https://tree.taiga.io/project/penpot/task/2608)
- Refactor of workspace toolbars [Taiga #2319](https://tree.taiga.io/project/penpot/us/2319) - Redesign of workspace toolbars [Taiga #2319](https://tree.taiga.io/project/penpot/us/2319)
### :bug: Bugs fixed ### :bug: Bugs fixed
### :arrow_up: Deps updates ### :arrow_up: Deps updates

View file

@ -34,7 +34,6 @@
} }
} }
ul.palette-menu .color-bullet { ul.palette-menu .color-bullet {
width: 20px; width: 20px;
height: 20px; height: 20px;
@ -88,7 +87,8 @@ ul.palette-menu .color-bullet {
border-radius: 50%; border-radius: 50%;
& .color-bullet-wrapper { & .color-bullet-wrapper {
background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAADFJREFUOE9jZGBgEAFifOANPknGUQMYhkkYEEgG+NMJKAwIAbwJbdQABnBCIgRoG4gAIF8IsXB/Rs4AAAAASUVORK5CYII=") left center; background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAADFJREFUOE9jZGBgEAFifOANPknGUQMYhkkYEEgG+NMJKAwIAbwJbdQABnBCIgRoG4gAIF8IsXB/Rs4AAAAASUVORK5CYII=")
left center;
background-color: $color-white; background-color: $color-white;
clip-path: circle(50%); clip-path: circle(50%);
display: flex; display: flex;
@ -98,7 +98,8 @@ ul.palette-menu .color-bullet {
} }
&.is-gradient { &.is-gradient {
background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAADFJREFUOE9jZGBgEAFifOANPknGUQMYhkkYEEgG+NMJKAwIAbwJbdQABnBCIgRoG4gAIF8IsXB/Rs4AAAAASUVORK5CYII=") left center; background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAADFJREFUOE9jZGBgEAFifOANPknGUQMYhkkYEEgG+NMJKAwIAbwJbdQABnBCIgRoG4gAIF8IsXB/Rs4AAAAASUVORK5CYII=")
left center;
background-color: $color-white; background-color: $color-white;
} }

View file

@ -177,7 +177,6 @@
} }
} }
} }
} }
.element-list.pages-list { .element-list.pages-list {
@ -214,17 +213,16 @@ button.collapse-sidebar {
} }
&.collapsed { &.collapsed {
background: $color-black; background: $color-gray-60;
left: 48px; left: 48px;
top: 48px; top: 48px;
width: 18px; width: 28px;
height: 24px; height: 48px;
padding: 0; padding: 0;
border-radius: 0px 4px 4px 0px; border-radius: 0px 4px 4px 0px;
border-left: 1px solid $color-gray-50;
& svg { & svg {
width: 8px;
height: 8px;
transform: rotate(0deg); transform: rotate(0deg);
} }
} }

View file

@ -11,13 +11,15 @@
color: $color-white; color: $color-white;
} }
& .typography-font, & .typography-data { & .typography-font,
& .typography-data {
font-size: 16px; font-size: 16px;
color: #7B7D85; color: $color-gray-30;
} }
.no-text & { .no-text & {
& .typography-font, & .typography-data { & .typography-font,
& .typography-data {
display: none; display: none;
} }
} }

View file

@ -21,7 +21,8 @@ $height-palette-max: 80px;
user-select: none; user-select: none;
display: grid; display: grid;
grid-template-areas: "header header header header" grid-template-areas:
"header header header header"
"toolbar left-sidebar viewport right-sidebar" "toolbar left-sidebar viewport right-sidebar"
"toolbar left-sidebar color-palette right-sidebar"; "toolbar left-sidebar color-palette right-sidebar";
@ -48,7 +49,7 @@ $height-palette-max: 80px;
.settings-bar.settings-bar-right { .settings-bar.settings-bar-right {
min-width: $width-settings-bar; min-width: $width-settings-bar;
max-width: 500px; max-width: 500px;
width: var(--width, $width-settings-bar); width: $width-settings-bar;
grid-area: right-sidebar; grid-area: right-sidebar;
} }
@ -68,7 +69,6 @@ $height-palette-max: 80px;
} }
} }
.workspace-context-menu { .workspace-context-menu {
background-color: $color-white; background-color: $color-white;
border-radius: $br-small; border-radius: $br-small;

View file

@ -69,15 +69,9 @@
::mf/wrap [mf/memo]} ::mf/wrap [mf/memo]}
[props] [props]
(let [layout (obj/get props "layout") (let [layout (obj/get props "layout")
{:keys [on-pointer-down on-lost-pointer-capture on-mouse-move parent-ref size]}
(use-resize-hook :right-sidebar 255 255 500 :x true :right)
drawing-tool (:tool (mf/deref refs/workspace-drawing))] drawing-tool (:tool (mf/deref refs/workspace-drawing))]
[:aside.settings-bar.settings-bar-right {:ref parent-ref
:style #js {"--width" (str size "px")}} [:aside.settings-bar.settings-bar-right
[:div.resize-area {:on-pointer-down on-pointer-down
:on-lost-pointer-capture on-lost-pointer-capture
:on-mouse-move on-mouse-move}]
[:div.settings-bar-inside [:div.settings-bar-inside
(cond (cond
(= drawing-tool :comments) (= drawing-tool :comments)

View file

@ -52,7 +52,6 @@
[{:keys [local selected-ids current-file-id file-typographies shared-libs]}] [{:keys [local selected-ids current-file-id file-typographies shared-libs]}]
(let [state (mf/use-state {:show-menu false}) (let [state (mf/use-state {:show-menu false})
selected (mf/use-state :file) selected (mf/use-state :file)
file-id file-id
@ -116,18 +115,7 @@
{:on-click #(reset! selected :file)} {:on-click #(reset! selected :file)}
(when (= selected :file) i/tick) (when (= selected :file) i/tick)
[:div.library-name (str (tr "workspace.libraries.colors.file-library") [:div.library-name (str (tr "workspace.libraries.colors.file-library")
(str/format " (%s)" (count file-typographies)))]] (str/format " (%s)" (count file-typographies)))]]]]
#_[:li.palette-library
{:on-click #(st/emit! (mdc/change-palette-selected :recent))}
(when (= selected :recent) i/tick)
[:div.library-name (str (tr "workspace.libraries.colors.recent-colors")
(str/format " (%s)" (count recent-colors)))]
[:div.color-sample
(for [[idx color] (map-indexed vector (take 7 (reverse recent-colors))) ]
[:& cb/color-bullet {:key (str "color-" idx)
:color color}])]]
]]
[:div.color-palette-actions [:div.color-palette-actions
{:on-click #(swap! state assoc :show-menu true)} {:on-click #(swap! state assoc :show-menu true)}
@ -136,7 +124,7 @@
[:span.left-arrow {:on-click on-left-arrow-click} i/arrow-slide] [:span.left-arrow {:on-click on-left-arrow-click} i/arrow-slide]
[:div.color-palette-content {:ref container :on-wheel on-wheel} [:div.color-palette-content {:ref container :on-wheel on-wheel}
[:div.color-palette-inside {:style {:position "relative"}} [:div.color-palette-inside
(for [[idx item] (map-indexed vector current-typographies)] (for [[idx item] (map-indexed vector current-typographies)]
[:& typography-item [:& typography-item
{:key idx {:key idx
@ -145,9 +133,7 @@
:selected-ids selected-ids :selected-ids selected-ids
:typography item}])]] :typography item}])]]
[:span.right-arrow {:on-click on-right-arrow-click} i/arrow-slide]]) [:span.right-arrow {:on-click on-right-arrow-click} i/arrow-slide]]))
)
(def local-data (def local-data
(l/derived #(select-keys % [:editors]) refs/workspace-local =)) (l/derived #(select-keys % [:editors]) refs/workspace-local =))

View file

@ -367,7 +367,8 @@
[:* [:*
[:& rules/rules [:& rules/rules
{:zoom zoom {:zoom zoom
:vbox vbox}] :vbox vbox
:selected-shapes selected-shapes}]
[:& guides/viewport-guides [:& guides/viewport-guides
{:zoom zoom {:zoom zoom

View file

@ -8,7 +8,9 @@
(:require (:require
[app.common.colors :as colors] [app.common.colors :as colors]
[app.common.data :as d] [app.common.data :as d]
[app.common.geom.shapes :as gsh]
[app.common.math :as mth] [app.common.math :as mth]
[app.main.ui.hooks :as hooks]
[app.util.object :as obj] [app.util.object :as obj]
[rumext.alpha :as mf])) [rumext.alpha :as mf]))
@ -16,6 +18,11 @@
(def rules-size 4) (def rules-size 4)
(def rules-width 1) (def rules-width 1)
(def rule-area-size 22)
(def rule-area-half-size (/ rule-area-size 2))
(def rules-background "var(--color-gray-50)")
;; ---------------- ;; ----------------
;; RULES ;; RULES
;; ---------------- ;; ----------------
@ -59,12 +66,12 @@
(let [x (:x vbox) (let [x (:x vbox)
y (:y vbox) y (:y vbox)
width (:width vbox) width (:width vbox)
height (/ 22 zoom)] height (/ rule-area-size zoom)]
{:x x :y y :width width :height height}) {:x x :y y :width width :height height})
(let [x (:x vbox) (let [x (:x vbox)
y (+ (:y vbox) (/ 22 zoom)) y (+ (:y vbox) (/ rule-area-size zoom))
width (/ 22 zoom) width (/ rule-area-size zoom)
height (- (:height vbox) (/ 21 zoom))] height (- (:height vbox) (/ 21 zoom))]
{:x x :y y :width width :height height}))) {:x x :y y :width width :height height})))
@ -107,7 +114,7 @@
[:* [:*
(let [{:keys [x y width height]} (get-background-area vbox zoom axis)] (let [{:keys [x y width height]} (get-background-area vbox zoom axis)]
[:rect {:x x :y y :width width :height height :style {:fill "#303236"}}]) [:rect {:x x :y y :width width :height height :style {:fill rules-background}}])
[:g.rules {:clipPath (str "url(#" clip-id ")")} [:g.rules {:clipPath (str "url(#" clip-id ")")}
@ -147,13 +154,118 @@
:style {:stroke colors/gray-30 :style {:stroke colors/gray-30
:stroke-width rules-width}}]])))]])) :stroke-width rules-width}}]])))]]))
(def selection-area-color "var(--color-primary)")
(def selection-area-opacity 0.3)
(def over-number-size 50)
(def over-number-opacity 0.7)
(mf/defc selection-area
[{:keys [vbox zoom selection-rect]}]
[:g.selection-area
[:g
[:rect {:x (:x selection-rect)
:y (:y vbox)
:width (:width selection-rect)
:height (/ rule-area-size zoom)
:style {:fill selection-area-color
:fill-opacity selection-area-opacity}}]
[:rect {:x (- (:x selection-rect) (/ over-number-size zoom))
:y (:y vbox)
:width (/ over-number-size zoom)
:height (/ rule-area-size zoom)
:style {:fill rules-background
:fill-opacity over-number-opacity}}]
[:text {:x (- (:x1 selection-rect) (/ 4 zoom))
:y (+ (:y vbox) (/ 12 zoom))
:text-anchor "end"
:dominant-baseline "middle"
:style {:font-size (/ 13 zoom)
:font-family "sourcesanspro"
:fill selection-area-color}}
(str (mth/round (:x1 selection-rect)))]
[:rect {:x (:x2 selection-rect)
:y (:y vbox)
:width (/ over-number-size zoom)
:height (/ rule-area-size zoom)
:style {:fill rules-background
:fill-opacity over-number-opacity}}]
[:text {:x (+ (:x2 selection-rect) (/ 4 zoom))
:y (+ (:y vbox) (/ 12 zoom))
:text-anchor "start"
:dominant-baseline "middle"
:style {:font-size (/ 13 zoom)
:font-family "sourcesanspro"
:fill selection-area-color}}
(str (mth/round (:x2 selection-rect)))]]
(let [center-x (+ (:x vbox) (/ rule-area-half-size zoom))
center-y (- (+ (:y selection-rect) (/ (:height selection-rect) 2)) (/ rule-area-half-size zoom))]
[:g {:transform (str "rotate(-90 " center-x "," center-y ")")}
[:rect {:x (- center-x (/ (:height selection-rect) 2) (/ rule-area-half-size zoom))
:y (- center-y (/ rule-area-half-size zoom))
:width (:height selection-rect)
:height (/ rule-area-size zoom)
:style {:fill selection-area-color
:fill-opacity selection-area-opacity}}]
[:rect {:x (- center-x (/ (:height selection-rect) 2) (/ rule-area-half-size zoom) (/ over-number-size zoom))
:y (- center-y (/ rule-area-half-size zoom))
:width (/ over-number-size zoom)
:height (/ rule-area-size zoom)
:style {:fill rules-background
:fill-opacity over-number-opacity}}]
[:rect {:x (+ (- center-x (/ (:height selection-rect) 2) (/ rule-area-half-size zoom) ) (:height selection-rect))
:y (- center-y (/ rule-area-half-size zoom))
:width (/ over-number-size zoom)
:height (/ rule-area-size zoom)
:style {:fill rules-background
:fill-opacity over-number-opacity}}]
[:text {:x (- center-x (/ (:height selection-rect) 2) (/ 15 zoom))
:y center-y
:text-anchor "end"
:dominant-baseline "middle"
:style {:font-size (/ 13 zoom)
:font-family "sourcesanspro"
:fill selection-area-color}}
(str (mth/round (:y2 selection-rect)))]
[:text {:x (+ center-x (/ (:height selection-rect) 2) )
:y center-y
:text-anchor "start"
:dominant-baseline "middle"
:style {:font-size (/ 13 zoom)
:font-family "sourcesanspro"
:fill selection-area-color}}
(str (mth/round (:y1 selection-rect)))]])])
(mf/defc rules (mf/defc rules
{::mf/wrap-props false {::mf/wrap-props false
::mf/wrap [mf/memo]} ::mf/wrap [#(mf/memo' % (mf/check-props ["zoom" "vbox" "selected-shapes"]))]}
[props] [props]
(let [zoom (obj/get props "zoom") (let [zoom (obj/get props "zoom")
vbox (obj/get props "vbox")] vbox (obj/get props "vbox")
selected-shapes (-> (obj/get props "selected-shapes")
(hooks/use-equal-memo))
selection-rect
(mf/use-memo
(mf/deps selected-shapes)
#(when (d/not-empty? selected-shapes)
(gsh/selection-rect selected-shapes)))]
(when (some? vbox) (when (some? vbox)
[:g.rules {:pointer-events "none"} [:g.rules {:pointer-events "none"}
[:& rules-axis {:zoom zoom :vbox vbox :axis :x}] [:& rules-axis {:zoom zoom :vbox vbox :axis :x}]
[:& rules-axis {:zoom zoom :vbox vbox :axis :y}]]))) [:& rules-axis {:zoom zoom :vbox vbox :axis :y}]
(when (some? selection-rect)
[:& selection-area {:zoom zoom
:vbox vbox
:selection-rect selection-rect}])])))