mirror of
https://github.com/penpot/penpot.git
synced 2026-04-25 11:18:36 +00:00
✨ Add visibility toggle for strokes (#8913)
* ✨ Add visibility toggle for strokes * ♻️ Use single emit! call for stroke visibility toggle * 💄 Disable stroke controls when hidden, matching shadow/blur pattern When a stroke is hidden, the alignment/style selects, cap selects, and cap switch button are now disabled. A .hidden CSS class dims the options area with reduced opacity. This matches the existing behavior in shadow_row and blur menu where controls are disabled when the effect is hidden. * 💄 Move stroke hide button before remove button --------- Signed-off-by: eureka928 <meobius123@gmail.com>
This commit is contained in:
parent
9106a994f1
commit
4703fe6e3b
@ -29,6 +29,7 @@
|
||||
- Add per-group add button for typographies (by @eureka928) [Github #5275](https://github.com/penpot/penpot/issues/5275)
|
||||
- Use page name for multi-export ZIP/PDF downloads (by @Dexterity104) [Github #8773](https://github.com/penpot/penpot/issues/8773)
|
||||
- Make links in comments clickable (by @eureka928) [Github #1602](https://github.com/penpot/penpot/issues/1602)
|
||||
- Add visibility toggle for strokes (by @eureka928) [Github #7438](https://github.com/penpot/penpot/issues/7438)
|
||||
|
||||
### :bug: Bugs fixed
|
||||
|
||||
|
||||
@ -145,7 +145,8 @@
|
||||
[::sm/one-of stroke-caps]]
|
||||
[:stroke-color {:optional true} clr/schema:hex-color]
|
||||
[:stroke-color-gradient {:optional true} clr/schema:gradient]
|
||||
[:stroke-image {:optional true} clr/schema:image]])
|
||||
[:stroke-image {:optional true} clr/schema:image]
|
||||
[:hidden {:optional true} :boolean]])
|
||||
|
||||
(def stroke-attrs
|
||||
"A set of attrs that corresponds to stroke data type"
|
||||
|
||||
@ -509,7 +509,8 @@
|
||||
|
||||
(when (some? shape-strokes)
|
||||
[:> :g props
|
||||
(for [[index value] (reverse (d/enumerate shape-strokes))]
|
||||
(for [[index value] (reverse (d/enumerate shape-strokes))
|
||||
:when (not (:hidden value))]
|
||||
[:& shape-custom-stroke {:shape shape
|
||||
:stroke value
|
||||
:index index
|
||||
|
||||
@ -12,6 +12,7 @@
|
||||
[app.common.types.stroke :as cts]
|
||||
[app.main.data.workspace :as udw]
|
||||
[app.main.data.workspace.colors :as dc]
|
||||
[app.main.data.workspace.shapes :as dwsh]
|
||||
[app.main.data.workspace.tokens.application :as dwta]
|
||||
[app.main.store :as st]
|
||||
[app.main.ui.components.title-bar :refer [title-bar*]]
|
||||
@ -155,6 +156,13 @@
|
||||
(st/emit! (udw/trigger-bounding-box-cloaking ids))
|
||||
(st/emit! (dc/change-stroke-attrs ids {:stroke-cap-start stroke-cap-end
|
||||
:stroke-cap-end stroke-cap-start} index)))))
|
||||
on-toggle-visibility
|
||||
(mf/use-fn
|
||||
(mf/deps ids)
|
||||
(fn [index]
|
||||
(st/emit! (udw/trigger-bounding-box-cloaking ids)
|
||||
(dwsh/update-shapes ids #(update-in % [:strokes index :hidden] not)))))
|
||||
|
||||
on-add-stroke
|
||||
(fn [_]
|
||||
(st/emit! (udw/trigger-bounding-box-cloaking ids))
|
||||
@ -226,6 +234,7 @@
|
||||
:applied-tokens (when (= 0 index) applied-tokens)
|
||||
:on-detach-token on-detach-token
|
||||
:on-remove on-remove
|
||||
:on-toggle-visibility on-toggle-visibility
|
||||
:on-reorder handle-reorder
|
||||
:disable-drag disable-drag
|
||||
:on-focus on-focus
|
||||
|
||||
@ -40,6 +40,7 @@
|
||||
on-stroke-cap-start-change
|
||||
on-stroke-cap-end-change
|
||||
on-stroke-cap-switch
|
||||
on-toggle-visibility
|
||||
disable-drag
|
||||
on-focus
|
||||
on-blur
|
||||
@ -49,7 +50,9 @@
|
||||
select-on-focus
|
||||
ids]}]
|
||||
|
||||
(let [token-numeric-inputs
|
||||
(let [hidden? (:hidden stroke)
|
||||
|
||||
token-numeric-inputs
|
||||
(features/use-feature "tokens/numeric-input")
|
||||
|
||||
on-drop
|
||||
@ -182,10 +185,18 @@
|
||||
on-cap-switch
|
||||
(mf/use-fn
|
||||
(mf/deps index on-stroke-cap-switch)
|
||||
#(on-stroke-cap-switch index))]
|
||||
#(on-stroke-cap-switch index))
|
||||
|
||||
on-toggle-visibility
|
||||
(mf/use-fn
|
||||
(mf/deps index on-toggle-visibility)
|
||||
(fn []
|
||||
(when on-toggle-visibility
|
||||
(on-toggle-visibility index))))]
|
||||
|
||||
[:div {:class (stl/css-case
|
||||
:stroke-data true
|
||||
:hidden hidden?
|
||||
:dnd-over-top (= (:over dprops) :top)
|
||||
:dnd-over-bot (= (:over dprops) :bot))
|
||||
:aria-label (str "stroke-row-" index)}
|
||||
@ -195,22 +206,33 @@
|
||||
|
||||
;; Stroke Color
|
||||
;; FIXME: memorize stroke color
|
||||
[:> color-row* {:color (ctc/stroke->color stroke)
|
||||
:index index
|
||||
:title title
|
||||
:on-change on-color-change-refactor
|
||||
:on-detach on-color-detach
|
||||
:on-remove on-remove
|
||||
:disable-drag disable-drag
|
||||
:applied-token (if (= index 0)
|
||||
stroke-color-token
|
||||
nil)
|
||||
:on-detach-token on-detach-token-color
|
||||
:on-token-change on-token-change
|
||||
:on-focus on-focus
|
||||
:origin :stroke-color
|
||||
:select-on-focus select-on-focus
|
||||
:on-blur on-blur}]
|
||||
[:div {:class (stl/css :stroke-color-actions)}
|
||||
[:> color-row* {:color (ctc/stroke->color stroke)
|
||||
:index index
|
||||
:title title
|
||||
:on-change on-color-change-refactor
|
||||
:on-detach on-color-detach
|
||||
:disable-drag disable-drag
|
||||
:applied-token (if (= index 0)
|
||||
stroke-color-token
|
||||
nil)
|
||||
:on-detach-token on-detach-token-color
|
||||
:on-token-change on-token-change
|
||||
:on-focus on-focus
|
||||
:origin :stroke-color
|
||||
:select-on-focus select-on-focus
|
||||
:on-blur on-blur}]
|
||||
|
||||
(when (some? on-toggle-visibility)
|
||||
[:> icon-button* {:variant "ghost"
|
||||
:aria-label (tr "workspace.options.stroke.toggle-stroke")
|
||||
:on-click on-toggle-visibility
|
||||
:icon (if hidden? "hide" "shown")}])
|
||||
|
||||
[:> icon-button* {:variant "ghost"
|
||||
:aria-label (tr "workspace.options.stroke.remove-stroke")
|
||||
:on-click on-remove
|
||||
:icon i/remove}]]
|
||||
|
||||
;; Stroke Width, Alignment & Style
|
||||
(if token-numeric-inputs
|
||||
@ -230,6 +252,7 @@
|
||||
:options stroke-alignment-options
|
||||
:variant "icon-only"
|
||||
:data-testid "stroke.alignment"
|
||||
:disabled hidden?
|
||||
:wrapper-class (stl/css :stroke-align-icon-select)
|
||||
:on-change on-alignment-change}]
|
||||
|
||||
@ -239,6 +262,7 @@
|
||||
:wrapper-class (stl/css :stroke-style-icon-select)
|
||||
:data-testid "stroke.style"
|
||||
:variant "icon-only"
|
||||
:disabled hidden?
|
||||
:dropdown-alignment :right
|
||||
:on-change on-style-change}])]
|
||||
|
||||
@ -258,6 +282,7 @@
|
||||
:data-testid "stroke.alignment"}
|
||||
[:& select {:default-value stroke-alignment
|
||||
:options stroke-alignment-options
|
||||
:disabled hidden?
|
||||
:on-change on-alignment-change}]]
|
||||
|
||||
(when-not disable-stroke-style
|
||||
@ -265,6 +290,7 @@
|
||||
:data-testid "stroke.style"}
|
||||
[:& select {:default-value stroke-style
|
||||
:options stroke-style-options
|
||||
:disabled hidden?
|
||||
:on-change on-style-change}]])])
|
||||
|
||||
;; Stroke Caps
|
||||
@ -272,11 +298,14 @@
|
||||
[:div {:class (stl/css :stroke-caps-options)}
|
||||
[:& select {:default-value (:stroke-cap-start stroke)
|
||||
:options stroke-caps-options
|
||||
:disabled hidden?
|
||||
:on-change on-caps-start-change}]
|
||||
[:> icon-button* {:variant "secondary"
|
||||
:aria-label (tr "labels.switch")
|
||||
:disabled hidden?
|
||||
:on-click on-cap-switch
|
||||
:icon i/switch}]
|
||||
[:& select {:default-value (:stroke-cap-end stroke)
|
||||
:options stroke-caps-options
|
||||
:disabled hidden?
|
||||
:on-change on-caps-end-change}]])]))
|
||||
|
||||
@ -27,6 +27,25 @@
|
||||
&.dnd-over-bot {
|
||||
--reorder-bottom-display: block;
|
||||
}
|
||||
|
||||
&.hidden {
|
||||
.stroke-options,
|
||||
.stroke-options-tokens,
|
||||
.stroke-caps-options {
|
||||
opacity: 0.5;
|
||||
pointer-events: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.stroke-color-actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
> :first-child {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.stroke-options {
|
||||
|
||||
@ -558,45 +558,46 @@
|
||||
[shape-id strokes thumbnail?]
|
||||
(h/call wasm/internal-module "_clear_shape_strokes")
|
||||
(keep (fn [stroke]
|
||||
(let [opacity (or (:stroke-opacity stroke) 1.0)
|
||||
color (:stroke-color stroke)
|
||||
gradient (:stroke-color-gradient stroke)
|
||||
image (:stroke-image stroke)
|
||||
width (:stroke-width stroke)
|
||||
align (:stroke-alignment stroke)
|
||||
style (-> stroke :stroke-style sr/translate-stroke-style)
|
||||
cap-start (-> stroke :stroke-cap-start sr/translate-stroke-cap)
|
||||
cap-end (-> stroke :stroke-cap-end sr/translate-stroke-cap)
|
||||
offset (mem/alloc types.fills.impl/FILL-U8-SIZE)
|
||||
heap (mem/get-heap-u8)
|
||||
dview (js/DataView. (.-buffer heap))]
|
||||
(case align
|
||||
:inner (h/call wasm/internal-module "_add_shape_inner_stroke" width style cap-start cap-end)
|
||||
:outer (h/call wasm/internal-module "_add_shape_outer_stroke" width style cap-start cap-end)
|
||||
(h/call wasm/internal-module "_add_shape_center_stroke" width style cap-start cap-end))
|
||||
(when-not (:hidden stroke)
|
||||
(let [opacity (or (:stroke-opacity stroke) 1.0)
|
||||
color (:stroke-color stroke)
|
||||
gradient (:stroke-color-gradient stroke)
|
||||
image (:stroke-image stroke)
|
||||
width (:stroke-width stroke)
|
||||
align (:stroke-alignment stroke)
|
||||
style (-> stroke :stroke-style sr/translate-stroke-style)
|
||||
cap-start (-> stroke :stroke-cap-start sr/translate-stroke-cap)
|
||||
cap-end (-> stroke :stroke-cap-end sr/translate-stroke-cap)
|
||||
offset (mem/alloc types.fills.impl/FILL-U8-SIZE)
|
||||
heap (mem/get-heap-u8)
|
||||
dview (js/DataView. (.-buffer heap))]
|
||||
(case align
|
||||
:inner (h/call wasm/internal-module "_add_shape_inner_stroke" width style cap-start cap-end)
|
||||
:outer (h/call wasm/internal-module "_add_shape_outer_stroke" width style cap-start cap-end)
|
||||
(h/call wasm/internal-module "_add_shape_center_stroke" width style cap-start cap-end))
|
||||
|
||||
(cond
|
||||
(some? gradient)
|
||||
(do
|
||||
(types.fills.impl/write-gradient-fill offset dview opacity gradient)
|
||||
(h/call wasm/internal-module "_add_shape_stroke_fill"))
|
||||
(cond
|
||||
(some? gradient)
|
||||
(do
|
||||
(types.fills.impl/write-gradient-fill offset dview opacity gradient)
|
||||
(h/call wasm/internal-module "_add_shape_stroke_fill"))
|
||||
|
||||
(some? image)
|
||||
(let [image-id (get image :id)
|
||||
buffer (uuid/get-u32 image-id)
|
||||
cached-image? (h/call wasm/internal-module "_is_image_cached"
|
||||
(aget buffer 0) (aget buffer 1)
|
||||
(aget buffer 2) (aget buffer 3)
|
||||
thumbnail?)]
|
||||
(types.fills.impl/write-image-fill offset dview opacity image)
|
||||
(h/call wasm/internal-module "_add_shape_stroke_fill")
|
||||
(when (== cached-image? 0)
|
||||
(fetch-image shape-id image-id thumbnail?)))
|
||||
(some? image)
|
||||
(let [image-id (get image :id)
|
||||
buffer (uuid/get-u32 image-id)
|
||||
cached-image? (h/call wasm/internal-module "_is_image_cached"
|
||||
(aget buffer 0) (aget buffer 1)
|
||||
(aget buffer 2) (aget buffer 3)
|
||||
thumbnail?)]
|
||||
(types.fills.impl/write-image-fill offset dview opacity image)
|
||||
(h/call wasm/internal-module "_add_shape_stroke_fill")
|
||||
(when (== cached-image? 0)
|
||||
(fetch-image shape-id image-id thumbnail?)))
|
||||
|
||||
(some? color)
|
||||
(do
|
||||
(types.fills.impl/write-solid-fill offset dview opacity color)
|
||||
(h/call wasm/internal-module "_add_shape_stroke_fill")))))
|
||||
(some? color)
|
||||
(do
|
||||
(types.fills.impl/write-solid-fill offset dview opacity color)
|
||||
(h/call wasm/internal-module "_add_shape_stroke_fill"))))))
|
||||
strokes))
|
||||
|
||||
(defn set-shape-svg-attrs
|
||||
|
||||
@ -7316,6 +7316,10 @@ msgstr "Outside"
|
||||
msgid "workspace.options.stroke.remove-stroke"
|
||||
msgstr "Remove stroke"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options/rows/stroke_row.cljs
|
||||
msgid "workspace.options.stroke.toggle-stroke"
|
||||
msgstr "Toggle stroke"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options/rows/stroke_row.cljs:137
|
||||
msgid "workspace.options.stroke.solid"
|
||||
msgstr "Solid"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user