🐛 Fix positioning of comment thread draft (#6357)

* 🐛 Fix positioning of comment thread draft

* 📚 Update changelog
This commit is contained in:
Belén Albeza 2025-04-24 09:53:07 +02:00 committed by GitHub
parent 9c4896d72b
commit b958dcb891
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 99 additions and 49 deletions

View file

@ -16,6 +16,7 @@
### :bug: Bugs fixed ### :bug: Bugs fixed
- Fix positioning of comment drafts when near the right / bottom edges of viewport [Taiga #10534](https://tree.taiga.io/project/penpot/issue/10534)
- Fix path having a wrong selrect [Taiga #10257](https://tree.taiga.io/project/penpot/issue/10257) - Fix path having a wrong selrect [Taiga #10257](https://tree.taiga.io/project/penpot/issue/10257)
- Fix SVG `stroke-linecap` property when importing SVGs [Taiga #9489](https://tree.taiga.io/project/penpot/issue/9489) - Fix SVG `stroke-linecap` property when importing SVGs [Taiga #9489](https://tree.taiga.io/project/penpot/issue/9489)
- Fix position problems cutting-pasting a component [Taiga #10677](https://tree.taiga.io/project/penpot/issue/10677) - Fix position problems cutting-pasting a component [Taiga #10677](https://tree.taiga.io/project/penpot/issue/10677)

View file

@ -759,9 +759,29 @@
[:> comment-form-buttons* {:on-submit on-submit* [:> comment-form-buttons* {:on-submit on-submit*
:on-cancel on-cancel :on-cancel on-cancel
:is-disabled disabled?}]])) :is-disabled disabled?}]]))
(defn- offset-position [position viewport zoom bubble-margin]
(let [viewport (or viewport {:offset-x 0 :offset-y 0 :width 0 :height 0})
base-x (+ (* (:x position) zoom) (:offset-x viewport))
base-y (+ (* (:y position) zoom) (:offset-y viewport))
x (:x position)
y (:y position)
w (:width viewport)
h (:height viewport)
comment-width 284 ;; TODO: this is the width set via CSS in an outer container…
;; We should probably do this in a different way.
orientation-left? (>= (+ base-x comment-width (:x bubble-margin)) w)
orientation-top? (>= base-y (/ h 2))
h-dir (if orientation-left? :left :right)
v-dir (if orientation-top? :top :bottom)]
{:x x :y y :h-dir h-dir :v-dir v-dir}))
(mf/defc comment-floating-thread-draft* (mf/defc comment-floating-thread-draft*
[{:keys [draft zoom on-cancel on-submit position-modifier]}] [{:keys [draft zoom on-cancel on-submit position-modifier viewport]}]
(let [profile (mf/deref refs/profile) (let [profile (mf/deref refs/profile)
mentions-s (mf/use-memo #(rx/subject)) mentions-s (mf/use-memo #(rx/subject))
@ -770,9 +790,14 @@
(some? position-modifier) (some? position-modifier)
(gpt/transform position-modifier)) (gpt/transform position-modifier))
content (:content draft) content (:content draft)
bubble-margin (gpt/point 0 0)
pos-x (* (:x position) zoom) pos (offset-position position viewport zoom bubble-margin)
pos-y (* (:y position) zoom)
margin-x (* (:x bubble-margin) (if (= (:h-dir pos) :left) -1 1))
margin-y (* (:y bubble-margin) (if (= (:v-dir pos) :top) -1 1))
pos-x (+ (* (:x pos) zoom) margin-x)
pos-y (- (* (:y pos) zoom) margin-y)
disabled? (or (blank-content? content) disabled? (or (blank-content? content)
(exceeds-length? content)) (exceeds-length? content))
@ -799,33 +824,39 @@
(on-submit draft)))] (on-submit draft)))]
[:> (mf/provider mentions-context) {:value mentions-s} [:> (mf/provider mentions-context) {:value mentions-s}
[:div [:div {:class (stl/css-case :floating-thread-draft-wrapper true
{:class (stl/css :floating-preview-wrapper) :left (= (:h-dir pos) :left)
:data-testid "floating-thread-bubble" :top (= (:v-dir pos) :top))
:style {:top (str pos-y "px") :style {:top (str pos-y "px")
:left (str pos-x "px")} :left (str pos-x "px")}}
:on-click dom/stop-propagation} [:div
[:> comment-avatar* {:class (stl/css :avatar-lg) {:data-testid "floating-thread-bubble"
:image (cfg/resolve-profile-photo-url profile)}]] :style {:top (str pos-y "px")
[:div {:class (stl/css :floating-thread-wrapper :cursor-auto) :left (str pos-x "px")}
:style {:top (str (- pos-y 24) "px") :on-click dom/stop-propagation}
:left (str (+ pos-x 28) "px")} [:> comment-avatar* {:class (stl/css :avatar-lg)
:on-click dom/stop-propagation} :image (cfg/resolve-profile-photo-url profile)}]]
[:div {:class (stl/css :form)} [:div {:class (stl/css :floating-thread-draft-inner-wrapper
[:> comment-input* :cursor-auto)
{:placeholder (tr "labels.write-new-comment") :style {:top (str (- pos-y 24) "px")
:value (or content "") :left (str (+ pos-x 28) "px")}
:autofocus true
:on-esc on-esc :on-click dom/stop-propagation}
:on-change on-change [:div {:class (stl/css :form)}
:on-ctrl-enter on-submit*}] [:> comment-input*
(when (exceeds-length? content) {:placeholder (tr "labels.write-new-comment")
[:div {:class (stl/css :error-text)} :value (or content "")
(tr "errors.character-limit-exceeded")]) :autofocus true
[:> comment-form-buttons* {:on-submit on-submit* :on-esc on-esc
:on-cancel on-esc :on-change on-change
:is-disabled disabled?}]] :on-ctrl-enter on-submit*}]
[:> mentions-panel*]]])) (when (exceeds-length? content)
[:div {:class (stl/css :error-text)}
(tr "errors.character-limit-exceeded")])
[:> comment-form-buttons* {:on-submit on-submit*
:on-cancel on-esc
:is-disabled disabled?}]]
[:> mentions-panel*]]]]))
(mf/defc comment-floating-thread-header* (mf/defc comment-floating-thread-header*
{::mf/private true} {::mf/private true}
@ -977,26 +1008,7 @@
[thread-id] [thread-id]
(l/derived (l/in [:comments thread-id]) st/state)) (l/derived (l/in [:comments thread-id]) st/state))
(defn- offset-position [position viewport zoom bubble-margin]
(let [viewport (or viewport {:offset-x 0 :offset-y 0 :width 0 :height 0})
base-x (+ (* (:x position) zoom) (:offset-x viewport))
base-y (+ (* (:y position) zoom) (:offset-y viewport))
x (:x position)
y (:y position)
w (:width viewport)
h (:height viewport)
comment-width 284 ;; TODO: this is the width set via CSS in an outer container…
;; We should probably do this in a different way.
orientation-left? (>= (+ base-x comment-width (:x bubble-margin)) w)
orientation-top? (>= base-y (/ h 2))
h-dir (if orientation-left? :left :right)
v-dir (if orientation-top? :top :bottom)]
{:x x :y y :h-dir h-dir :v-dir v-dir}))
(mf/defc comment-floating-thread* (mf/defc comment-floating-thread*
{::mf/wrap [mf/memo]} {::mf/wrap [mf/memo]}

View file

@ -160,6 +160,40 @@
z-index: initial; z-index: initial;
} }
.floating-thread-draft-wrapper {
position: absolute;
display: flex;
flex-direction: row;
column-gap: $s-12;
--translate-x: 0%;
--translate-y: 0%;
transform: translate(var(--translate-x), var(--translate-y));
&.left {
--translate-x: -100%;
flex-direction: row-reverse;
}
&.top {
--translate-y: -100%;
align-items: flex-end;
}
}
.floating-thread-draft-inner-wrapper {
display: flex;
flex-direction: column;
gap: $s-12;
width: $s-284;
padding: $s-8 $s-12 $s-8 $s-12;
pointer-events: auto;
border-radius: $br-8;
border: $s-2 solid var(--modal-border-color);
background-color: var(--comment-modal-background-color);
max-height: var(--comment-height);
}
.floating-preview-displacement { .floating-preview-displacement {
margin-left: calc(-1 * ($s-12 + $s-2)); margin-left: calc(-1 * ($s-12 + $s-2));
margin-top: calc(-1 * ($s-8 + $s-2)); margin-top: calc(-1 * ($s-8 + $s-2));
@ -177,6 +211,7 @@
border: $s-2 solid var(--modal-border-color); border: $s-2 solid var(--modal-border-color);
background-color: var(--comment-modal-background-color); background-color: var(--comment-modal-background-color);
max-height: var(--comment-height); max-height: var(--comment-height);
--translate-x: 0%; --translate-x: 0%;
--translate-y: 0%; --translate-y: 0%;
transform: translate(var(--translate-x), var(--translate-y)); transform: translate(var(--translate-x), var(--translate-y));

View file

@ -231,6 +231,7 @@
:position-modifier modifier1 :position-modifier modifier1
:on-cancel on-draft-cancel :on-cancel on-draft-cancel
:on-submit on-draft-submit :on-submit on-draft-submit
:viewport nil
:zoom zoom}])]]])) :zoom zoom}])]]]))
(mf/defc comments-sidebar* (mf/defc comments-sidebar*

View file

@ -86,4 +86,5 @@
{:draft draft {:draft draft
:on-cancel on-draft-cancel :on-cancel on-draft-cancel
:on-submit on-draft-submit :on-submit on-draft-submit
:viewport viewport
:zoom zoom}])]]])) :zoom zoom}])]]]))