diff --git a/frontend/resources/styles/main/partials/modal.scss b/frontend/resources/styles/main/partials/modal.scss index adb1d3d7e..6e200c7b3 100644 --- a/frontend/resources/styles/main/partials/modal.scss +++ b/frontend/resources/styles/main/partials/modal.scss @@ -280,11 +280,13 @@ .item-name { color: $color-gray-60; font-size: $fs14; + margin-right: calc(4.5rem + 1rem); } .item-contents { color: $color-gray-40; font-size: $fs12; + margin-right: calc(4.5rem + 1rem); } .item-button { diff --git a/frontend/resources/styles/main/partials/viewer-header.scss b/frontend/resources/styles/main/partials/viewer-header.scss index 1edb9a0ac..21c1e75c7 100644 --- a/frontend/resources/styles/main/partials/viewer-header.scss +++ b/frontend/resources/styles/main/partials/viewer-header.scss @@ -213,6 +213,20 @@ overflow: hidden; .link { + &:before { + content: ''; + position: absolute; + width: 50%; + background: linear-gradient(45deg, transparent, #ffffff); + height: 100%; + top: 0; + left: 0; + pointer-events: none; + margin-left: 50%; + } + overflow: hidden; + white-space: nowrap; + position: relative; color: $color-gray-50; line-height: 1.5; user-select: all; diff --git a/frontend/src/app/main/data/workspace/groups.cljs b/frontend/src/app/main/data/workspace/groups.cljs index 32324c854..4bb6736a0 100644 --- a/frontend/src/app/main/data/workspace/groups.cljs +++ b/frontend/src/app/main/data/workspace/groups.cljs @@ -131,6 +131,7 @@ (let [page-id (:current-page-id state) objects (dwc/lookup-page-objects state page-id) selected (get-in state [:workspace-local :selected]) + selected (cp/clean-loops objects selected) shapes (shapes-for-grouping objects selected)] (when-not (empty? shapes) (let [;; If the selected shape is a group, we can use it. If not, diff --git a/frontend/src/app/main/exports.cljs b/frontend/src/app/main/exports.cljs index ecf860ce2..ae08c7045 100644 --- a/frontend/src/app/main/exports.cljs +++ b/frontend/src/app/main/exports.cljs @@ -19,6 +19,7 @@ [app.common.geom.align :as gal] [app.common.geom.point :as gpt] [app.common.geom.matrix :as gmt] + [app.util.timers :as ts] [app.main.ui.shapes.filters :as filters] [app.main.ui.shapes.frame :as frame] [app.main.ui.shapes.circle :as circle] @@ -185,7 +186,8 @@ [:& wrapper {:shape frame :view-box vbox}]])) (mf/defc component-svg - {::mf/wrap [mf/memo]} + {::mf/wrap [mf/memo + #(mf/deferred % ts/idle-then-raf)]} [{:keys [objects group zoom] :or {zoom 1} :as props}] (let [modifier (-> (gpt/point (:x group) (:y group)) (gpt/negate) diff --git a/frontend/src/app/main/ui/components/context_menu.cljs b/frontend/src/app/main/ui/components/context_menu.cljs index d912a587c..86b257333 100644 --- a/frontend/src/app/main/ui/components/context_menu.cljs +++ b/frontend/src/app/main/ui/components/context_menu.cljs @@ -13,7 +13,8 @@ [goog.object :as gobj] [app.main.ui.components.dropdown :refer [dropdown']] [app.common.uuid :as uuid] - [app.util.data :refer [classnames]])) + [app.util.data :refer [classnames]] + [app.util.dom :as dom])) (mf/defc context-menu {::mf/wrap-props false} @@ -27,14 +28,31 @@ is-selectable (gobj/get props "selectable") selected (gobj/get props "selected") top (gobj/get props "top") - left (gobj/get props "left")] + left (gobj/get props "left") + + offset (mf/use-state 0) + + check-menu-offscreen + (mf/use-callback + (mf/deps top @offset) + (fn [node] + (when node + (let [{node-height :height} (dom/get-bounding-rect node) + {window-height :height} (dom/get-window-size) + target-offset (if (> (+ top node-height) window-height) + (- node-height) + 0)] + + (if (not= target-offset @offset) + (reset! offset target-offset))))))] + (when open? [:> dropdown' props [:div.context-menu {:class (classnames :is-open open? :is-selectable is-selectable) - :style {:top top + :style {:top (+ top @offset) :left left}} - [:ul.context-menu-items + [:ul.context-menu-items {:ref check-menu-offscreen} (for [[action-name action-handler] options] [:li.context-menu-item {:class (classnames :is-selected (and selected (= action-name selected))) :key action-name}