Recalculate token context-menu submenu position

This commit is contained in:
Xavier Julian 2025-03-06 14:12:29 +01:00 committed by Xaviju
parent a361e0b990
commit 390cf6b642
2 changed files with 29 additions and 36 deletions

View file

@ -307,47 +307,46 @@
(mf/defc menu-entry (mf/defc menu-entry
{::mf/props :obj} {::mf/props :obj}
[{:keys [title value hint on-click selected? children submenu-offset submenu-direction no-selectable]}] [{:keys [title value hint on-click selected? children submenu-offset no-selectable]}]
(let [submenu-ref (mf/use-ref nil) (let [submenu-ref (mf/use-ref nil)
hovering? (mf/use-ref false) hovering? (mf/use-ref false)
parent-menu-dom-element-pos* (mf/use-state nil)
parent-menu-dom-element-pos (deref parent-menu-dom-element-pos*)
is-submenu-outside* (mf/use-state false)
is-submenu-outside? (deref is-submenu-outside*)
hint? (and hint (seq hint)) hint? (and hint (seq hint))
on-pointer-enter on-pointer-enter
(mf/use-fn (mf/use-fn
(mf/deps is-submenu-outside?)
(fn [] (fn []
(mf/set-ref-val! hovering? true) (mf/set-ref-val! hovering? true)
(when-let [submenu-node (mf/ref-val submenu-ref)] (when-let [submenu-node (mf/ref-val submenu-ref)]
(dom/set-css-property! submenu-node "display" "block")))) (dom/set-css-property! submenu-node "display" "block")
(reset! is-submenu-outside* (dom/is-element-outside? submenu-node)))))
on-pointer-leave on-pointer-leave
(mf/use-fn (mf/use-fn
(mf/deps is-submenu-outside?)
(fn [] (fn []
(mf/set-ref-val! hovering? false) (mf/set-ref-val! hovering? false)
(when-let [submenu-node (mf/ref-val submenu-ref)] (when-let [submenu-node (mf/ref-val submenu-ref)]
(timers/schedule 50 #(when-not (mf/ref-val hovering?) (timers/schedule 50 #(when-not (mf/ref-val hovering?)
(dom/set-css-property! submenu-node "display" "none")))))) (dom/set-css-property! submenu-node "display" "none")
(reset! is-submenu-outside* false))))))
set-dom-node get-parent-menu-entry-position
(mf/use-fn (mf/use-fn
(fn [dom] (fn [parent-menu-dom-element]
(let [submenu-node (mf/ref-val submenu-ref)]
(when (and (some? dom) (some? submenu-node) (= submenu-direction "up"))
(dom/set-css-property! submenu-node "top" "unset"))
(when (and (some? dom) (some? submenu-node) (= submenu-direction "down"))
(dom/set-css-property! submenu-node "top" (dm/str (.-offsetTop dom) "px"))))))]
(mf/use-effect (when (some? parent-menu-dom-element)
(mf/deps submenu-direction) (reset! parent-menu-dom-element-pos* (dm/str (.-offsetTop parent-menu-dom-element) "px")))))]
(fn []
(let [submenu-node (mf/ref-val submenu-ref)]
(when (= submenu-direction "up")
(dom/set-css-property! submenu-node "top" "unset")))))
[:li {:class (stl/css-case [:li {:class (stl/css-case
:context-menu-item true :context-menu-item true
:context-menu-item-selected (and (not no-selectable) selected?) :context-menu-item-selected (and (not no-selectable) selected?)
:context-menu-item-unselected (and (not no-selectable) (not selected?)) :context-menu-item-unselected (and (not no-selectable) (not selected?))
:context-menu-item-hint-wrapper hint?) :context-menu-item-hint-wrapper hint?)
:ref set-dom-node :ref get-parent-menu-entry-position
:data-value value :data-value value
:on-click on-click :on-click on-click
:on-pointer-enter on-pointer-enter :on-pointer-enter on-pointer-enter
@ -361,21 +360,17 @@
(when children (when children
[:* [:*
[:> icon* {:icon-id "arrow" :size "s"}] [:> icon* {:icon-id "arrow" :size "s"}]
[:ul {:class (stl/css :token-context-submenu) [:ul {:ref submenu-ref
:data-direction submenu-direction :class (stl/css-case
:ref submenu-ref :token-context-submenu true
;; Under review: This distances are arbitrary, :token-context-submenu-top is-submenu-outside?)
;; https://tree.taiga.io/project/penpot/task/9627 :style {:left (dm/str submenu-offset "px")
:style {:display "none" :top (if is-submenu-outside? "unset" parent-menu-dom-element-pos)}
:--dist (if (= submenu-direction "down")
"-80px"
"80px")
:left (dm/str submenu-offset "px")}
:on-context-menu prevent-default} :on-context-menu prevent-default}
children]])])) children]])]))
(mf/defc menu-tree (mf/defc menu-tree
[{:keys [selected-shapes submenu-offset submenu-direction type errors] :as context-data}] [{:keys [selected-shapes submenu-offset type errors] :as context-data}]
(let [entries (if (and (not (some? errors)) (let [entries (if (and (not (some? errors))
(seq selected-shapes)) (seq selected-shapes))
(if (some? type) (if (some? type)
@ -389,7 +384,6 @@
submenu [:& menu-entry {:title title submenu [:& menu-entry {:title title
:hint hint :hint hint
:no-selectable true :no-selectable true
:submenu-direction submenu-direction
:submenu-offset submenu-offset} :submenu-offset submenu-offset}
[:& menu-tree (assoc context-data :type submenu)]] [:& menu-tree (assoc context-data :type submenu)]]
:else [:& menu-entry :else [:& menu-entry
@ -400,7 +394,7 @@
:selected? selected?}])]))) :selected? selected?}])])))
(mf/defc token-context-menu-tree (mf/defc token-context-menu-tree
[{:keys [width direction errors] :as mdata}] [{:keys [width errors] :as mdata}]
(let [objects (mf/deref refs/workspace-page-objects) (let [objects (mf/deref refs/workspace-page-objects)
selected (mf/deref refs/selected-shapes) selected (mf/deref refs/selected-shapes)
selected-shapes (into [] (keep (d/getf objects)) selected) selected-shapes (into [] (keep (d/getf objects)) selected)
@ -409,7 +403,6 @@
selected-token-set-name (mf/deref refs/selected-token-set-name)] selected-token-set-name (mf/deref refs/selected-token-set-name)]
[:ul {:class (stl/css :context-list)} [:ul {:class (stl/css :context-list)}
[:& menu-tree {:submenu-offset width [:& menu-tree {:submenu-offset width
:submenu-direction direction
:token token :token token
:errors errors :errors errors
:selected-token-set-name selected-token-set-name :selected-token-set-name selected-token-set-name
@ -463,5 +456,5 @@
:left (dm/str left "px")} :left (dm/str left "px")}
:on-context-menu prevent-default} :on-context-menu prevent-default}
(when mdata (when mdata
[:& token-context-menu-tree (assoc mdata :width @width :direction dropdown-direction)])]]) [:& token-context-menu-tree (assoc mdata :width @width)])]])
(dom/get-body))))) (dom/get-body)))))

View file

@ -33,12 +33,12 @@
overflow-y: auto; overflow-y: auto;
} }
.token-context-submenu[data-direction="up"] { .token-context-submenu {
bottom: var(--dist); display: none;
} }
.token-context-submenu[data-direction="down"] { .token-context-submenu-top {
top: var(--dist); bottom: 80px;
} }
.token-context-submenu { .token-context-submenu {