mirror of
https://github.com/penpot/penpot.git
synced 2026-04-25 11:18:36 +00:00
✨ Add color customization for ruler guides (#8986)
* ✨ Add customizable colors for ruler guides * ✨ Update CHANGES.md * 💄 Move guide color menu styles to SCSS * 💄 Fix trailing whitespace in guides.cljs --------- Signed-off-by: Dexterity <173429049+Dexterity104@users.noreply.github.com> Signed-off-by: Andrey Antukh <niwi@niwi.nz> Co-authored-by: Andrey Antukh <niwi@niwi.nz>
This commit is contained in:
parent
cd320c0cd6
commit
e1d3106f61
@ -38,6 +38,7 @@
|
||||
- Add guide locking and fix locked elements not selectable in viewer (by @Dexterity104) [Github #8358](https://github.com/penpot/penpot/issues/8358)
|
||||
- Apply styles to selection (by @AzazelN28) [Taiga #13647](https://tree.taiga.io/project/penpot/task/13647)
|
||||
- Reorder prototyping overlay options to show Position before Relative to (by @rockchris099) [Github #2910](https://github.com/penpot/penpot/issues/2910)
|
||||
- Add customizable colors for ruler guides (by @Dexterity104) [Github #5199](https://github.com/penpot/penpot/issues/5199)
|
||||
- Persist asset search query and section filter when switching sidebar tabs (by @eureka0928) [Github #2913](https://github.com/penpot/penpot/issues/2913)
|
||||
- Add delete and duplicate buttons to typography dialog (by @eureka0928) [Github #5270](https://github.com/penpot/penpot/issues/5270)
|
||||
- Edit ruler guide position by double-clicking the guide pill (by @eureka0928) [Github #2311](https://github.com/penpot/penpot/issues/2311)
|
||||
|
||||
@ -34,7 +34,8 @@
|
||||
[:id ::sm/uuid]
|
||||
[:axis [::sm/one-of #{:x :y}]]
|
||||
[:position ::sm/safe-number]
|
||||
[:frame-id {:optional true} [:maybe ::sm/uuid]]])
|
||||
[:frame-id {:optional true} [:maybe ::sm/uuid]]
|
||||
[:color {:optional true} [:maybe ctc/schema:hex-color]]])
|
||||
|
||||
(def schema:guides
|
||||
[:map-of {:gen/max 2} ::sm/uuid schema:guide])
|
||||
|
||||
@ -1195,6 +1195,16 @@
|
||||
(-> params (assoc :kind :grid-cells
|
||||
:grid grid
|
||||
:cells cells))))))))
|
||||
(defn show-guide-context-menu
|
||||
[{:keys [position guide] :as params}]
|
||||
(dm/assert! (gpt/point? position))
|
||||
(ptk/reify ::show-guide-context-menu
|
||||
ptk/WatchEvent
|
||||
(watch [_ _ _]
|
||||
(rx/of (show-context-menu
|
||||
(-> params (assoc :kind :guide
|
||||
:guide guide)))))))
|
||||
|
||||
(def hide-context-menu
|
||||
(ptk/reify ::hide-context-menu
|
||||
ptk/UpdateEvent
|
||||
|
||||
@ -152,6 +152,23 @@
|
||||
(map build-move-event)
|
||||
(rx/from))))))
|
||||
|
||||
(defn update-guide-color
|
||||
[guide-id color]
|
||||
(ptk/reify ::update-guide-color
|
||||
ptk/WatchEvent
|
||||
(watch [it state _]
|
||||
(let [{:keys [guides] :as page} (dsh/lookup-page state)
|
||||
guide (get guides guide-id)]
|
||||
(when (some? guide)
|
||||
(let [updated-guide (if (some? color)
|
||||
(assoc guide :color color)
|
||||
(dissoc guide :color))
|
||||
changes
|
||||
(-> (pcb/empty-changes it)
|
||||
(pcb/with-page page)
|
||||
(pcb/set-guide guide-id updated-guide))]
|
||||
(rx/of (dwc/commit-changes changes))))))))
|
||||
|
||||
(defn set-hover-guide
|
||||
[id hover?]
|
||||
(ptk/reify ::set-hover-guide
|
||||
|
||||
@ -899,6 +899,50 @@
|
||||
:disabled (not has-copied-tracks?)}]]))
|
||||
|
||||
|
||||
(def guide-color-presets
|
||||
["#ff3277" "#4dabf7" "#51cf66" "#fcc419" "#ff922b" "#cc5de8" "#ffffff" "#868e96"])
|
||||
|
||||
(mf/defc guide-color-context-menu*
|
||||
{::mf/props :obj
|
||||
::mf/private true}
|
||||
[{:keys [mdata]}]
|
||||
(let [{:keys [guide]} mdata
|
||||
guide-id (:id guide)
|
||||
current-color (or (:color guide) (first guide-color-presets))
|
||||
|
||||
do-set-color
|
||||
(mf/use-fn
|
||||
(mf/deps guide-id)
|
||||
(fn [event]
|
||||
(let [color (dom/get-data (dom/get-current-target event) "color")]
|
||||
(st/emit! dw/hide-context-menu
|
||||
(dwg/update-guide-color guide-id color)))))
|
||||
|
||||
do-remove-guide
|
||||
(mf/use-fn
|
||||
(mf/deps guide)
|
||||
(fn []
|
||||
(st/emit! dw/hide-context-menu
|
||||
(dwg/remove-guide guide))))]
|
||||
|
||||
[:*
|
||||
[:li {:class (stl/css :context-menu-item :guide-color-label)}
|
||||
[:span {:class (stl/css :title)}
|
||||
(tr "workspace.context-menu.guides.change-color")]]
|
||||
[:li {:class (stl/css :guide-color-swatches)}
|
||||
(for [color guide-color-presets]
|
||||
[:span {:key color
|
||||
:class (stl/css-case
|
||||
:guide-color-swatch true
|
||||
:selected (= color current-color))
|
||||
:data-color color
|
||||
:on-click do-set-color
|
||||
:title color
|
||||
:style {:background-color color}}])]
|
||||
[:> menu-separator* {}]
|
||||
[:> menu-entry* {:title (tr "workspace.context-menu.guides.remove")
|
||||
:on-click do-remove-guide}]]))
|
||||
|
||||
;; FIXME: optimize because it is rendered always
|
||||
|
||||
(mf/defc context-menu*
|
||||
@ -936,4 +980,5 @@
|
||||
:page [:> page-item-context-menu* {:mdata mdata}]
|
||||
:grid-track [:> grid-track-context-menu* {:mdata mdata}]
|
||||
:grid-cells [:> grid-cells-context-menu* {:mdata mdata}]
|
||||
:guide [:> guide-color-context-menu* {:mdata mdata}]
|
||||
[:> viewport-context-menu* {:mdata mdata}]))]]]))
|
||||
|
||||
@ -138,3 +138,30 @@
|
||||
pointer-events: none;
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
.guide-color-label {
|
||||
cursor: default;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.guide-color-swatches {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: deprecated.$s-6;
|
||||
padding: deprecated.$s-4 deprecated.$s-6 deprecated.$s-8;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
.guide-color-swatch {
|
||||
width: deprecated.$s-20;
|
||||
height: deprecated.$s-20;
|
||||
border-radius: 50%;
|
||||
cursor: pointer;
|
||||
flex-shrink: 0;
|
||||
box-sizing: border-box;
|
||||
border: deprecated.$s-2 solid var(--panel-border-color);
|
||||
|
||||
&.selected {
|
||||
border: deprecated.$s-2 solid var(--menu-foreground-color);
|
||||
}
|
||||
}
|
||||
|
||||
@ -31,7 +31,8 @@
|
||||
(def ^:const guide-width 1)
|
||||
(def ^:const guide-opacity 0.7)
|
||||
(def ^:const guide-opacity-hover 1)
|
||||
(def ^:const guide-color colors/new-danger)
|
||||
(def ^:const default-guide-color colors/new-danger)
|
||||
|
||||
(def ^:const guide-pill-width 34)
|
||||
(def ^:const guide-pill-height 20)
|
||||
(def ^:const guide-pill-corner-radius 4)
|
||||
@ -285,10 +286,14 @@
|
||||
(mf/defc guide*
|
||||
{::mf/wrap [mf/memo]}
|
||||
[{:keys [guide is-hover on-guide-change get-hover-frame vbox zoom
|
||||
hover-frame disabled-guides frame-modifier frame-transform]}]
|
||||
hover-frame disabled-guides frame-modifier frame-transform
|
||||
on-guide-context-menu]}]
|
||||
(let [axis
|
||||
(get guide :axis)
|
||||
|
||||
guide-color
|
||||
(or (:color guide) default-guide-color)
|
||||
|
||||
read-only?
|
||||
(mf/use-ctx ctx/workspace-read-only?)
|
||||
|
||||
@ -303,7 +308,7 @@
|
||||
|
||||
handle-change-position
|
||||
(mf/use-fn
|
||||
(mf/deps on-guide-change)
|
||||
(mf/deps on-guide-change guide)
|
||||
(fn [changes]
|
||||
(when on-guide-change
|
||||
(on-guide-change (merge guide changes)))))
|
||||
@ -399,7 +404,13 @@
|
||||
(not (ctst/rotated-frame? frame))))
|
||||
[:g.guide-area {:opacity (when frame-guide-outside? 0)}
|
||||
(when-not disabled-guides
|
||||
(let [{:keys [x y width height]} (guide-area-axis pos vbox zoom frame axis)]
|
||||
(let [{:keys [x y width height]} (guide-area-axis pos vbox zoom frame axis)
|
||||
on-context-menu
|
||||
(fn [event]
|
||||
(dom/prevent-default event)
|
||||
(dom/stop-propagation event)
|
||||
(when on-guide-context-menu
|
||||
(on-guide-context-menu event guide)))]
|
||||
[:rect {:x x
|
||||
:y y
|
||||
:width width
|
||||
@ -413,6 +424,7 @@
|
||||
:on-pointer-up on-pointer-up
|
||||
:on-lost-pointer-capture on-lost-pointer-capture
|
||||
:on-pointer-move on-pointer-move
|
||||
:on-context-menu on-context-menu
|
||||
:on-double-click on-double-click}]))
|
||||
|
||||
(if (some? frame)
|
||||
@ -597,6 +609,13 @@
|
||||
(st/emit! (dw/update-guides guide))
|
||||
(st/emit! (dw/remove-guide guide)))))
|
||||
|
||||
on-guide-context-menu
|
||||
(mf/use-fn
|
||||
(fn [event guide]
|
||||
(let [position (dom/get-client-position event)]
|
||||
(st/emit! (dw/show-guide-context-menu {:position position
|
||||
:guide guide})))))
|
||||
|
||||
frame-modifiers
|
||||
(-> (group-by :id modifiers)
|
||||
(update-vals (comp :transform first)))]
|
||||
@ -628,4 +647,5 @@
|
||||
:frame-transform (get frame-modifiers frame-id)
|
||||
:get-hover-frame get-hover-frame
|
||||
:on-guide-change on-guide-change
|
||||
:on-guide-context-menu on-guide-context-menu
|
||||
:disabled-guides disabled-guides}]))]))
|
||||
|
||||
@ -94,6 +94,22 @@
|
||||
value)]
|
||||
(st/emit! (dwgu/update-guides (assoc guide :position position))))))}
|
||||
|
||||
:color
|
||||
{:this true
|
||||
:get
|
||||
(fn [self]
|
||||
(-> self u/proxy->ruler-guide :color))
|
||||
|
||||
:set
|
||||
(fn [self value]
|
||||
(cond
|
||||
(not (r/check-permission plugin-id "content:write"))
|
||||
(u/not-valid plugin-id :color "Plugin doesn't have 'content:write' permission")
|
||||
|
||||
:else
|
||||
(let [guide (u/proxy->ruler-guide self)]
|
||||
(st/emit! (dwgu/update-guides (assoc guide :color value))))))}
|
||||
|
||||
:remove
|
||||
(fn []
|
||||
(let [guide (u/locate-ruler-guide file-id page-id id)]
|
||||
|
||||
@ -5730,6 +5730,12 @@ msgstr "Copy columns"
|
||||
msgid "workspace.context-menu.grid-cells.paste-tracks"
|
||||
msgstr "Paste"
|
||||
|
||||
msgid "workspace.context-menu.guides.change-color"
|
||||
msgstr "Guide color"
|
||||
|
||||
msgid "workspace.context-menu.guides.remove"
|
||||
msgstr "Remove guide"
|
||||
|
||||
#: src/app/main/ui/workspace/context_menu.cljs:754
|
||||
msgid "workspace.context-menu.grid-track.column.add-after"
|
||||
msgstr "Add 1 column to the right"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user