diff --git a/CHANGES.md b/CHANGES.md index 2b9527806..4a05df7f6 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -74,6 +74,7 @@ - Fix dashboard scrolling using 'Page Up' and 'Page Down' [Taiga #5081](https://tree.taiga.io/project/penpot/issue/5081) - Fix view mode header buttons overlapping in small resolutions [Taiga #5058](https://tree.taiga.io/project/penpot/issue/5058) - Fix precision for wrap in flex [Taiga #5072](https://tree.taiga.io/project/penpot/issue/5072) +- Fix relative position overlay positioning [Taiga #5092](https://tree.taiga.io/project/penpot/issue/5092) ### :heart: Community contributions by (Thank you!) - To @ondrejkonec: for contributing to the code with: diff --git a/frontend/src/app/main/ui/viewer/shapes.cljs b/frontend/src/app/main/ui/viewer/shapes.cljs index ffc33bfbe..99c59c22c 100644 --- a/frontend/src/app/main/ui/viewer/shapes.cljs +++ b/frontend/src/app/main/ui/viewer/shapes.cljs @@ -7,6 +7,7 @@ (ns app.main.ui.viewer.shapes "The main container for a frame in viewer mode" (:require + [app.common.geom.point :as gpt] [app.common.geom.shapes :as gsh] [app.common.pages.helpers :as cph] [app.common.types.shape.interactions :as ctsi] @@ -46,80 +47,88 @@ (defn- activate-interaction [interaction shape base-frame frame-offset objects overlays] - (case (:action-type interaction) - :navigate - (when-let [frame-id (:destination interaction)] - (let [viewer-section (dom/get-element "viewer-section") - scroll (if (:preserve-scroll interaction) - (dom/get-scroll-pos viewer-section) - 0)] - (st/emit! (dv/set-nav-scroll scroll) - (dv/go-to-frame frame-id (:animation interaction))))) - :open-overlay - (let [dest-frame-id (:destination interaction) - viewer-objects (deref (refs/get-viewer-objects)) - dest-frame (get viewer-objects dest-frame-id) - relative-to-id (if (= :manual (:overlay-pos-type interaction)) - (:id shape) ;; manual interactions are allways from "self" - (:position-relative-to interaction)) - relative-to-shape (or (get objects relative-to-id) base-frame) - close-click-outside (:close-click-outside interaction) - background-overlay (:background-overlay interaction) - overlays-ids (set (map :id overlays)) - relative-to-base-frame (find-relative-to-base-frame relative-to-shape objects overlays-ids base-frame) - position (ctsi/calc-overlay-position interaction - viewer-objects - relative-to-shape - relative-to-base-frame - dest-frame - frame-offset)] - (when dest-frame-id - (st/emit! (dv/open-overlay dest-frame-id - position - close-click-outside - background-overlay - (:animation interaction))))) + (let [;; When the interactive item is inside a nested frame we need to add to the offset the position + ;; of the parent-frame otherwise the position won't match + shape-frame (cph/get-frame objects shape) - :toggle-overlay - (let [frame-id (:destination interaction) - dest-frame (get objects frame-id) - relative-to-id (if (= :manual (:overlay-pos-type interaction)) - (:id shape) ;; manual interactions are allways from "self" - (:position-relative-to interaction)) - relative-to-shape (or (get objects relative-to-id) base-frame) - overlays-ids (set (map :id overlays)) - relative-to-base-frame (find-relative-to-base-frame relative-to-shape objects overlays-ids base-frame) - position (ctsi/calc-overlay-position interaction - objects - relative-to-shape - relative-to-base-frame - dest-frame - frame-offset) + frame-offset (if (or (cph/root-frame? shape-frame) (cph/root? shape-frame)) + frame-offset + (gpt/add frame-offset (gpt/point shape-frame)))] + (case (:action-type interaction) + :navigate + (when-let [frame-id (:destination interaction)] + (let [viewer-section (dom/get-element "viewer-section") + scroll (if (:preserve-scroll interaction) + (dom/get-scroll-pos viewer-section) + 0)] + (st/emit! (dv/set-nav-scroll scroll) + (dv/go-to-frame frame-id (:animation interaction))))) - close-click-outside (:close-click-outside interaction) - background-overlay (:background-overlay interaction)] - (when frame-id - (st/emit! (dv/toggle-overlay frame-id + :open-overlay + (let [dest-frame-id (:destination interaction) + viewer-objects (deref (refs/get-viewer-objects)) + dest-frame (get viewer-objects dest-frame-id) + relative-to-id (if (= :manual (:overlay-pos-type interaction)) + (:id shape) ;; manual interactions are allways from "self" + (:position-relative-to interaction)) + relative-to-shape (or (get objects relative-to-id) base-frame) + close-click-outside (:close-click-outside interaction) + background-overlay (:background-overlay interaction) + overlays-ids (set (map :id overlays)) + relative-to-base-frame (find-relative-to-base-frame relative-to-shape objects overlays-ids base-frame) + position (ctsi/calc-overlay-position interaction + viewer-objects + relative-to-shape + relative-to-base-frame + dest-frame + frame-offset)] + (when dest-frame-id + (st/emit! (dv/open-overlay dest-frame-id position close-click-outside background-overlay (:animation interaction))))) - :close-overlay - (let [frame-id (or (:destination interaction) - (if (= (:type shape) :frame) - (:id shape) - (:frame-id shape)))] - (st/emit! (dv/close-overlay frame-id (:animation interaction)))) + :toggle-overlay + (let [frame-id (:destination interaction) + dest-frame (get objects frame-id) + relative-to-id (if (= :manual (:overlay-pos-type interaction)) + (:id shape) ;; manual interactions are allways from "self" + (:position-relative-to interaction)) + relative-to-shape (or (get objects relative-to-id) base-frame) + overlays-ids (set (map :id overlays)) + relative-to-base-frame (find-relative-to-base-frame relative-to-shape objects overlays-ids base-frame) + position (ctsi/calc-overlay-position interaction + objects + relative-to-shape + relative-to-base-frame + dest-frame + frame-offset) - :prev-screen - (st/emit! (rt/nav-back-local)) + close-click-outside (:close-click-outside interaction) + background-overlay (:background-overlay interaction)] + (when frame-id + (st/emit! (dv/toggle-overlay frame-id + position + close-click-outside + background-overlay + (:animation interaction))))) - :open-url - (st/emit! (dom/open-new-window (:url interaction))) + :close-overlay + (let [frame-id (or (:destination interaction) + (if (= (:type shape) :frame) + (:id shape) + (:frame-id shape)))] + (st/emit! (dv/close-overlay frame-id (:animation interaction)))) - nil)) + :prev-screen + (st/emit! (rt/nav-back-local)) + + :open-url + (st/emit! (dom/open-new-window (:url interaction))) + + nil))) ;; Perform the opposite action of an interaction, if possible (defn- deactivate-interaction