diff --git a/frontend/src/app/main/data/workspace/colors.cljs b/frontend/src/app/main/data/workspace/colors.cljs
index 2b1a049de1..0ed40e3e2e 100644
--- a/frontend/src/app/main/data/workspace/colors.cljs
+++ b/frontend/src/app/main/data/workspace/colors.cljs
@@ -1148,12 +1148,3 @@
:position :right})
(ptk/event ::ev/event {::ev/name "add-asset-to-library"
:asset-type "color"}))))))
-
-(defn get-active-color-tab
- []
- (let [tab (::tab storage/user)]
- (or tab :ramp)))
-
-(defn set-active-color-tab!
- [tab]
- (swap! storage/user assoc ::tab tab))
diff --git a/frontend/src/app/main/ui/ds/layout/tab_switcher.cljs b/frontend/src/app/main/ui/ds/layout/tab_switcher.cljs
index 78f837fe86..af232e255a 100644
--- a/frontend/src/app/main/ui/ds/layout/tab_switcher.cljs
+++ b/frontend/src/app/main/ui/ds/layout/tab_switcher.cljs
@@ -6,29 +6,29 @@
(ns app.main.ui.ds.layout.tab-switcher
(:require-macros
- [app.common.data.macros :as dm]
[app.main.style :as stl])
(:require
+ [app.common.data :as d]
[app.main.ui.ds.foundations.assets.icon :refer [icon* icon-list]]
- [app.util.array :as array]
[app.util.dom :as dom]
[app.util.keyboard :as kbd]
[app.util.object :as obj]
- [rumext.v2 :as mf]))
+ [rumext.v2 :as mf]
+ [rumext.v2.util :as mfu]))
(mf/defc tab*
{::mf/private true}
- [{:keys [selected icon label aria-label id on-ref] :rest props}]
- (let [class (stl/css-case :tab true
- :selected selected)
+ [{:keys [selected icon label aria-label id ref] :rest props}]
+ (let [class (stl/css-case
+ :tab true
+ :selected selected)
props (mf/spread-props props
{:class class
:role "tab"
:aria-selected selected
:title (or label aria-label)
:tab-index (if selected nil -1)
- :ref (fn [node]
- (on-ref node id))
+ :ref ref
:data-id id
;; This prop is to be used for accessibility purposes only.
:id id})]
@@ -41,62 +41,57 @@
:aria-hidden (when label true)
:aria-label (when (not label) aria-label)}])
(when (string? label)
- [:span {:class (stl/css-case :tab-text true
- :tab-text-and-icon icon)}
+ [:span {:class (stl/css-case
+ :tab-text true
+ :tab-text-and-icon icon)}
label])]]))
(mf/defc tab-nav*
- {::mf/props :obj
- ::mf/private true}
- [{:keys [on-ref tabs selected on-click button-position action-button] :rest props}]
- (let [class (stl/css-case :tab-nav true
- :tab-nav-start (= "start" button-position)
- :tab-nav-end (= "end" button-position))
- props (mf/spread-props props
- {:class (stl/css :tab-list)
- :role "tablist"
- :aria-orientation "horizontal"})]
- [:nav {:class class}
+ {::mf/private true
+ ::mf/memo true}
+ [{:keys [ref tabs selected on-click button-position action-button] :rest props}]
+ (let [nav-class
+ (stl/css-case :tab-nav true
+ :tab-nav-start (= "start" button-position)
+ :tab-nav-end (= "end" button-position))
+ props
+ (mf/spread-props props
+ {:class (stl/css :tab-list)
+ :role "tablist"
+ :aria-orientation "horizontal"})]
+ [:nav {:class nav-class}
(when (= button-position "start")
action-button)
- [:> "ul" props
- (for [element ^js tabs]
- (let [icon (obj/get element "icon")
- label (obj/get element "label")
- aria-label (obj/get element "aria-label")
- id (obj/get element "id")]
+ [:> :ul props
+ (for [element tabs]
+ (let [icon (get element :icon)
+ label (get element :label)
+ aria-label (get element :aria-label)
+ id (get element :id)]
[:> tab* {:icon icon
- :key (dm/str "tab-" id)
+ :key id
:label label
:aria-label aria-label
:selected (= id selected)
:on-click on-click
- :on-ref on-ref
+ :ref ref
:id id}]))]
(when (= button-position "end")
action-button)]))
-(defn- get-tab
- [tabs id]
- (or (array/find #(= id (obj/get % "id")) tabs)
- (aget tabs 0)))
-
-(defn- get-selected-tab-id
- [tabs default]
- (let [tab (get-tab tabs default)]
- (obj/get tab "id")))
+(def ^:private schema:tab-attrs
+ [:map {:title "tab"}
+ [:icon {:optional true}
+ [:and :string [:fn #(contains? icon-list %)]]]
+ [:label {:optional true} :string]
+ [:aria-label {:optional true} :string]])
(def ^:private schema:tab
[:and
- [:map {:title "tab"}
- [:icon {:optional true}
- [:and :string [:fn #(contains? icon-list %)]]]
- [:label {:optional true} :string]
- [:aria-label {:optional true} :string]
- [:content some?]]
+ schema:tab-attrs
[:fn {:error/message "invalid data: missing required props"}
(fn [tab]
(or (and (contains? tab :icon)
@@ -108,95 +103,91 @@
[:map
[:tabs [:vector {:min 1} schema:tab]]
[:class {:optional true} :string]
- [:on-change-tab {:optional true} fn?]
- [:default-selected {:optional true} :string]
- [:selected {:optional true} :string]
+ [:on-change fn?]
+ [:selected :string]
[:action-button {:optional true} some?]
[:action-button-position {:optional true}
[:maybe [:enum "start" "end"]]]])
(mf/defc tab-switcher*
- {::mf/props :obj
- ::mf/schema schema:tab-switcher}
- [{:keys [tabs class on-change-tab default-selected selected action-button-position action-button] :rest props}]
- (let [selected* (mf/use-state #(or selected (get-selected-tab-id tabs default-selected)))
- selected (or selected (deref selected*))
+ {::mf/schema schema:tab-switcher}
+ [{:keys [tabs class on-change selected action-button-position action-button children] :rest props}]
+ (let [nodes-ref (mf/use-ref nil)
+
+ tabs
+ (if (array? tabs)
+ (mfu/bean tabs)
+ tabs)
- tabs-nodes-refs (mf/use-ref nil)
- tabs-ref (mf/use-ref nil)
on-click
(mf/use-fn
- (mf/deps on-change-tab)
+ (mf/deps on-change)
(fn [event]
(let [node (dom/get-current-target event)
id (dom/get-data node "id")]
- (reset! selected* id)
-
- (when (fn? on-change-tab)
- (on-change-tab id)))))
+ (when (fn? on-change)
+ (on-change id)))))
on-ref
(mf/use-fn
- (fn [node id]
- (let [refs (or (mf/ref-val tabs-nodes-refs) #js {})
- refs (if node
- (obj/set! refs id node)
- (obj/unset! refs id))]
- (mf/set-ref-val! tabs-nodes-refs refs))))
+ (fn [node]
+ (let [state (mf/ref-val nodes-ref)
+ state (d/nilv state #js {})
+ id (dom/get-data node "id")
+ state (obj/set! state id node)]
+ (mf/set-ref-val! nodes-ref state)
+ (fn []
+ (let [state (mf/ref-val nodes-ref)
+ state (d/nilv state #js {})
+ id (dom/get-data node "id")
+ state (obj/unset! state id)]
+ (mf/set-ref-val! nodes-ref state))))))
on-key-down
(mf/use-fn
- (mf/deps selected)
+ (mf/deps selected tabs on-change)
(fn [event]
- (let [tabs (mf/ref-val tabs-ref)
- len (alength tabs)
- sel? #(= selected (obj/get % "id"))
+ (let [len (count tabs)
+ sel? #(= selected (get % :id))
id (cond
(kbd/home? event)
- (let [tab (aget tabs 0)]
- (obj/get tab "id"))
+ (let [tab (nth tabs 0)]
+ (get tab :id))
(kbd/left-arrow? event)
- (let [index (array/find-index sel? tabs)
+ (let [index (d/index-of-pred tabs sel?)
index (mod (- index 1) len)
- tab (aget tabs index)]
- (obj/get tab "id"))
+ tab (nth tabs index)]
+ (get tab :id))
(kbd/right-arrow? event)
- (let [index (array/find-index sel? tabs)
+ (let [index (d/index-of-pred tabs sel?)
index (mod (+ index 1) len)
- tab (aget tabs index)]
- (obj/get tab "id")))]
+ tab (nth tabs index)]
+ (get tab :id)))]
(when (some? id)
- (reset! selected* id)
- (let [nodes (mf/ref-val tabs-nodes-refs)
+ (on-change id)
+ (let [nodes (mf/ref-val nodes-ref)
node (obj/get nodes id)]
(dom/focus! node))))))
- class (dm/str class " " (stl/css :tabs))
-
- props (mf/spread-props props {:class class})]
-
- (mf/with-effect [tabs]
- (mf/set-ref-val! tabs-ref tabs))
+ props
+ (mf/spread-props props {:class [class (stl/css :tabs)]})]
[:> :article props
[:div {:class (stl/css :padding-wrapper)}
[:> tab-nav* {:button-position action-button-position
:action-button action-button
:tabs tabs
- :on-ref on-ref
+ :ref on-ref
:selected selected
:on-key-down on-key-down
:on-click on-click}]]
- (let [active-tab (get-tab tabs selected)
- content (obj/get active-tab "content")
- id (obj/get active-tab "id")]
- [:section {:class (stl/css :tab-panel)
- :tab-index 0
- :role "tabpanel"
- :aria-labelledby id}
- content])]))
+ [:section {:class (stl/css :tab-panel)
+ :tab-index 0
+ :role "tabpanel"
+ :aria-labelledby selected}
+ children]]))
diff --git a/frontend/src/app/main/ui/ds/layout/tab_switcher.mdx b/frontend/src/app/main/ui/ds/layout/tab_switcher.mdx
index 2675bed01d..d145d33131 100644
--- a/frontend/src/app/main/ui/ds/layout/tab_switcher.mdx
+++ b/frontend/src/app/main/ui/ds/layout/tab_switcher.mdx
@@ -49,21 +49,33 @@ These are available in the `app.main.ds.foundations.assets.icon` namespace.
[app.main.ui.ds.foundations.assets.icon :as i]))
```
-```clj
-[:> tab_switcher*
- {:tabs [{ :label "Code"
- :id "tab-code"
- :icon i/fill-content
- :content [:p Lorem Ipsum ]}
- { :label "Design"
- :id "tab-design"
- :icon i/pentool
- :content [:p Dolor sit amet ]}
- { :label "Menu"
- :id "tab-menu"
- :icon i/mask
- :content [:p Consectetur adipiscing elit ]}
- ]}]
+```clojure
+(let [selected-tab* (mf/use-state "code")
+ selected-tab (deref selected-tab*)
+ on-change-tab (mf/use-fn #(reset! selected-tab* %))
+ tabs (mf/with-memo []
+ [{:label "Code"
+ :id "code"
+ :icon i/fill-content}
+ {:label "Design"
+ :id "design"
+ :icon i/pentool}
+ {:label "Menu"
+ :id "menu"
+ :icon i/mask}])]
+ [:> tab_switcher* {:tabs tabs
+ :selected selected-tab
+ :on-change on-change-tab}
+ (case selected-tab
+ "code"
+ [:p "Lorem Ipsum"]
+
+ "design"
+ [:p "Dolor sit amet"]
+
+ "menu"
+ [:p "Consectetur adipiscing elit"])])
+
```
diff --git a/frontend/src/app/main/ui/ds/layout/tab_switcher.stories.jsx b/frontend/src/app/main/ui/ds/layout/tab_switcher.stories.jsx
index daaeada1a2..33840f8802 100644
--- a/frontend/src/app/main/ui/ds/layout/tab_switcher.stories.jsx
+++ b/frontend/src/app/main/ui/ds/layout/tab_switcher.stories.jsx
@@ -13,9 +13,30 @@ const Padded = ({ children }) => (
{children}
);
+const TabSwitcherWrapper = ({tabs, ...props}) => {
+ const navTabs = tabs.map(({content, ...item}) => {
+ return item;
+ });
+
+ const [selected, setSelected] = React.useState(() => {
+ return props.default || tabs[0].id;
+ });
+
+ const content = tabs.reduce((result, tab) => {
+ result[tab.id] = tab.content;
+ return result;
+ }, {});
+
+ return (
+
+ {content[selected]}
+
+ );
+};
+
export default {
title: "Layout/Tab switcher",
- component: TabSwitcher,
+ component: TabSwitcherWrapper,
args: {
tabs: [
{
@@ -46,7 +67,7 @@ export default {
),
},
],
- defaultSelected: "tab-code",
+ default: "tab-code",
},
argTypes: {
actionButtonPosition: {
@@ -59,12 +80,12 @@ export default {
exclude: [
"tabs",
"actionButton",
- "defaultSelected",
+ "default",
"actionButtonPosition",
],
},
},
- render: ({ ...args }) => ,
+ render: ({ ...args }) => ,
};
export const Default = {};
diff --git a/frontend/src/app/main/ui/hooks.cljs b/frontend/src/app/main/ui/hooks.cljs
index 2458fbed67..bfc2399d2a 100644
--- a/frontend/src/app/main/ui/hooks.cljs
+++ b/frontend/src/app/main/ui/hooks.cljs
@@ -324,6 +324,22 @@
state*))
+(defn use-persisted-state
+ "A specialized hook that adds persistence to the default mf/use-state hook.
+
+ The state is automatically persisted under the provided key on
+ localStorage. And it will keep watching events with type equals to
+ `key` for new values."
+ [key default]
+ (let [id (mf/use-id)
+ state* (mf/use-state #(get storage/user key default))
+ state (deref state*)]
+
+ (mf/with-effect [state key id]
+ (swap! storage/user assoc key state))
+
+ state*))
+
(defonce ^:private intersection-subject (rx/subject))
(defonce ^:private intersection-observer
(delay (js/IntersectionObserver.
diff --git a/frontend/src/app/main/ui/inspect/right_sidebar.cljs b/frontend/src/app/main/ui/inspect/right_sidebar.cljs
index 8ef94c8e0d..d732f90922 100644
--- a/frontend/src/app/main/ui/inspect/right_sidebar.cljs
+++ b/frontend/src/app/main/ui/inspect/right_sidebar.cljs
@@ -38,7 +38,7 @@
(mf/defc right-sidebar
[{:keys [frame page objects file selected shapes page-id file-id share-id from on-change-section on-expand]
:or {from :viewer}}]
- (let [section (mf/use-state :info #_:code)
+ (let [section (mf/use-state #(do :info))
objects (or objects (:objects page))
shapes (or shapes
(resolve-shapes objects selected))
@@ -81,31 +81,13 @@
(fn []
(dom/open-new-window "https://help.penpot.app/user-guide/inspect/")))
- info-content
- (mf/html [:& attributes {:page-id page-id
- :objects objects
- :file-id file-id
- :frame frame
- :shapes shapes
- :from from
- :libraries libraries
- :share-id share-id}])
-
- code-content
- (mf/html [:& code {:frame frame
- :shapes shapes
- :on-expand handle-expand
- :from from}])
-
tabs
- #js [#js {:label (tr "inspect.tabs.info")
- :id "info"
- :content info-content}
-
- #js {:label (tr "inspect.tabs.code")
- :data-testid "code"
- :id "code"
- :content code-content}]]
+ (mf/with-memo []
+ [{:label (tr "inspect.tabs.info")
+ :id "info"}
+ {:label (tr "inspect.tabs.code")
+ :data-testid "code"
+ :id "code"}])]
(mf/use-effect
(mf/deps shapes handle-change-tab)
@@ -148,9 +130,25 @@
[:div {:class (stl/css :inspect-content)}
[:> tab-switcher* {:tabs tabs
- :default-selected "info"
- :on-change-tab handle-change-tab
- :class (stl/css :viewer-tab-switcher)}]]]
+ :selected (name @section)
+ :on-change handle-change-tab
+ :class (stl/css :viewer-tab-switcher)}
+ (case @section
+ :info
+ [:& attributes {:page-id page-id
+ :objects objects
+ :file-id file-id
+ :frame frame
+ :shapes shapes
+ :from from
+ :libraries libraries
+ :share-id share-id}]
+
+ :code
+ [:& code {:frame frame
+ :shapes shapes
+ :on-expand handle-expand
+ :from from}])]]]
[:div {:class (stl/css :empty)}
[:div {:class (stl/css :code-info)}
[:span {:class (stl/css :placeholder-icon)}
diff --git a/frontend/src/app/main/ui/workspace.cljs b/frontend/src/app/main/ui/workspace.cljs
index a7a905a397..b2c0b1192f 100644
--- a/frontend/src/app/main/ui/workspace.cljs
+++ b/frontend/src/app/main/ui/workspace.cljs
@@ -59,6 +59,13 @@
{:keys [vport] :as wlocal} (mf/deref refs/workspace-local)
{:keys [options-mode]} wglobal
+
+ ;; FIXME: pass this down to viewport and reuse it from here
+ ;; instead of making an other deref on viewport for the same
+ ;; data
+ drawing
+ (mf/deref refs/workspace-drawing)
+
colorpalette? (:colorpalette layout)
textpalette? (:textpalette layout)
hide-ui? (:hide-ui layout)
@@ -77,7 +84,7 @@
node-ref (use-resize-observer on-resize)]
[:*
- (when (not hide-ui?)
+ (when (not ^boolean hide-ui?)
[:& palette {:layout layout
:on-change-palette-size on-resize-palette}])
@@ -115,6 +122,7 @@
:page-id page-id}])
[:> right-sidebar* {:section options-mode
:selected selected
+ :drawing-tool (get drawing :tool)
:layout layout
:file file
:page-id page-id}]])]))
@@ -147,7 +155,8 @@
(-> file
(dissoc :data)
(assoc ::has-data (contains? file :data))))))
- st/state))
+ st/state
+ =))
(defn- make-page-ref
[file-id page-id]
diff --git a/frontend/src/app/main/ui/workspace/colorpicker.cljs b/frontend/src/app/main/ui/workspace/colorpicker.cljs
index e5c5548bca..147aa74991 100644
--- a/frontend/src/app/main/ui/workspace/colorpicker.cljs
+++ b/frontend/src/app/main/ui/workspace/colorpicker.cljs
@@ -29,6 +29,7 @@
[app.main.ui.components.select :refer [select]]
[app.main.ui.ds.foundations.assets.icon :as ic]
[app.main.ui.ds.layout.tab-switcher :refer [tab-switcher*]]
+ [app.main.ui.hooks :as hooks]
[app.main.ui.icons :as i]
[app.main.ui.workspace.colorpicker.color-inputs :refer [color-inputs]]
[app.main.ui.workspace.colorpicker.gradients :refer [gradients*]]
@@ -112,11 +113,14 @@
:linear :linear-gradient
:radial :radial-gradient)
:color))
- active-color-tab (mf/use-state #(dc/get-active-color-tab))
+
+ active-color-tab* (hooks/use-persisted-state ::color-tab "ramp")
+ active-color-tab (deref active-color-tab*)
+
drag?* (mf/use-state false)
drag? (deref drag?*)
- type (if (= @active-color-tab "hsva") :hsv :rgb)
+ type (if (= active-color-tab "hsva") :hsv :rgb)
fill-image-ref (mf/use-ref nil)
@@ -163,10 +167,7 @@
:checked keep-aspect-ratio?})))))
on-change-tab
- (mf/use-fn
- (fn [tab]
- (reset! active-color-tab tab)
- (dc/set-active-color-tab! tab)))
+ (mf/use-fn #(reset! active-color-tab* %))
handle-change-mode
(mf/use-fn
@@ -282,12 +283,10 @@
handle-stop-edit-start
(mf/use-fn
- (fn []
- (reset! should-update? false)))
+ #(reset! should-update? false))
handle-stop-edit-finish
(mf/use-fn
- (mf/deps state)
(fn []
(reset! should-update? true)
@@ -338,50 +337,24 @@
(fn [value]
(st/emit! (dc/update-colorpicker-gradient-opacity (/ value 100)))))
- cap-stops? (or (features/use-feature "render-wasm/v1") (contains? cfg/flags :frontend-binary-fills))
+ render-wasm?
+ (features/use-feature "render-wasm/v1")
+
+ cap-stops?
+ (or ^boolean render-wasm?
+ ^boolean (contains? cfg/flags :frontend-binary-fills))
tabs
- #js [#js {:aria-label (tr "workspace.libraries.colors.rgba")
- :icon ic/rgba
- :id "ramp"
- :content (mf/html (if picking-color?
- [:div {:class (stl/css :picker-detail-wrapper)}
- [:div {:class (stl/css :center-circle)}]
- [:canvas#picker-detail {:class (stl/css :picker-detail) :width 256 :height 140}]]
- [:> ramp-selector*
- {:color current-color
- :disable-opacity disable-opacity
- :on-change handle-change-color
- :on-start-drag on-start-drag
- :on-finish-drag on-finish-drag}]))}
-
- #js {:aria-label "Harmony"
- :icon ic/rgba-complementary
- :id "harmony"
- :content (mf/html (if picking-color?
- [:div {:class (stl/css :picker-detail-wrapper)}
- [:div {:class (stl/css :center-circle)}]
- [:canvas#picker-detail {:class (stl/css :picker-detail) :width 256 :height 140}]]
- [:& harmony-selector
- {:color current-color
- :disable-opacity disable-opacity
- :on-change handle-change-color
- :on-start-drag on-start-drag
- :on-finish-drag on-finish-drag}]))}
-
- #js {:aria-label "HSVA"
- :icon ic/hsva
- :id "hsva"
- :content (mf/html (if picking-color?
- [:div {:class (stl/css :picker-detail-wrapper)}
- [:div {:class (stl/css :center-circle)}]
- [:canvas#picker-detail {:class (stl/css :picker-detail) :width 256 :height 140}]]
- [:& hsva-selector
- {:color current-color
- :disable-opacity disable-opacity
- :on-change handle-change-color
- :on-start-drag on-start-drag
- :on-finish-drag on-finish-drag}]))}]]
+ (mf/with-memo []
+ [{:aria-label (tr "workspace.libraries.colors.rgba")
+ :icon ic/rgba
+ :id "ramp"}
+ {:aria-label "Harmony"
+ :icon ic/rgba-complementary
+ :id "harmony"}
+ {:aria-label "HSVA"
+ :icon ic/hsva
+ :id "hsva"}])]
;; Initialize colorpicker state
(mf/with-effect []
@@ -486,11 +459,41 @@
:multi false
:ref fill-image-ref
:on-selected on-fill-image-selected}]]])
+
[:*
[:div {:class (stl/css :colorpicker-tabs)}
[:> tab-switcher* {:tabs tabs
- :default-selected "ramp"
- :on-change-tab on-change-tab}]]
+ :selected active-color-tab
+ :on-change on-change-tab}
+ (if picking-color?
+ [:div {:class (stl/css :picker-detail-wrapper)}
+ [:div {:class (stl/css :center-circle)}]
+ [:canvas#picker-detail {:class (stl/css :picker-detail) :width 256 :height 140}]]
+
+
+ (case active-color-tab
+ "ramp"
+ [:> ramp-selector*
+ {:color current-color
+ :disable-opacity disable-opacity
+ :on-change handle-change-color
+ :on-start-drag on-start-drag
+ :on-finish-drag on-finish-drag}]
+
+ "harmony"
+ [:& harmony-selector
+ {:color current-color
+ :disable-opacity disable-opacity
+ :on-change handle-change-color
+ :on-start-drag on-start-drag}]
+
+ "hsva"
+ [:& hsva-selector
+ {:color current-color
+ :disable-opacity disable-opacity
+ :on-change handle-change-color
+ :on-start-drag on-start-drag
+ :on-finish-drag on-finish-drag}]))]]
[:& color-inputs
{:type type
diff --git a/frontend/src/app/main/ui/workspace/left_header.cljs b/frontend/src/app/main/ui/workspace/left_header.cljs
index 875907f016..44cad87617 100644
--- a/frontend/src/app/main/ui/workspace/left_header.cljs
+++ b/frontend/src/app/main/ui/workspace/left_header.cljs
@@ -26,8 +26,7 @@
;; --- Header Component
-(mf/defc left-header
- {::mf/props :obj}
+(mf/defc left-header*
[{:keys [file layout project page-id class]}]
(let [profile (mf/deref refs/profile)
file-id (:id file)
diff --git a/frontend/src/app/main/ui/workspace/libraries.cljs b/frontend/src/app/main/ui/workspace/libraries.cljs
index e00c06fc35..dcc676201b 100644
--- a/frontend/src/app/main/ui/workspace/libraries.cljs
+++ b/frontend/src/app/main/ui/workspace/libraries.cljs
@@ -565,7 +565,7 @@
(mf/defc libraries-dialog
{::mf/register modal/components
::mf/register-as :libraries-dialog}
- [{:keys [starting-tab file-id] :as props :or {starting-tab :libraries}}]
+ [{:keys [starting-tab file-id]}]
(let [files (mf/deref refs/files)
file (get files file-id)
shared? (:is-shared file)
@@ -596,24 +596,21 @@
(modal/hide!)
(modal/disallow-click-outside!)))
- libraries-tab
- (mf/html [:> libraries-tab*
- {:is-shared shared?
- :linked-libraries linked-libraries
- :shared-libraries shared-libraries}])
+ selected-tab*
+ (mf/use-state #(d/nilv starting-tab "libraries"))
- updates-tab
- (mf/html [:> updates-tab*
- {:file-id file-id
- :libraries linked-libraries}])
+ selected-tab
+ (deref selected-tab*)
+
+ on-change-tab
+ (mf/use-fn #(reset! selected-tab* %))
tabs
- #js [#js {:label (tr "workspace.libraries.libraries")
- :id "libraries"
- :content libraries-tab}
- #js {:label (tr "workspace.libraries.updates")
- :id "updates"
- :content updates-tab}]]
+ (mf/with-memo []
+ [{:label (tr "workspace.libraries.libraries")
+ :id "libraries"}
+ {:label (tr "workspace.libraries.updates")
+ :id "updates"}])]
(mf/with-effect []
(st/emit! (dtm/fetch-shared-files)))
@@ -631,7 +628,19 @@
(tr "workspace.libraries.libraries")]
[:> tab-switcher* {:tabs tabs
- :default-selected (dm/str starting-tab)}]]]))
+ :selected selected-tab
+ :on-change on-change-tab}
+ (case selected-tab
+ "libraries"
+ [:> libraries-tab*
+ {:is-shared shared?
+ :linked-libraries linked-libraries
+ :shared-libraries shared-libraries}]
+
+ "updates"
+ [:> updates-tab*
+ {:file-id file-id
+ :libraries linked-libraries}])]]]))
(mf/defc v2-info-dialog
{::mf/register modal/components
diff --git a/frontend/src/app/main/ui/workspace/sidebar.cljs b/frontend/src/app/main/ui/workspace/sidebar.cljs
index 564e8aa7df..11ce398f89 100644
--- a/frontend/src/app/main/ui/workspace/sidebar.cljs
+++ b/frontend/src/app/main/ui/workspace/sidebar.cljs
@@ -19,18 +19,19 @@
[app.main.ui.ds.buttons.icon-button :refer [icon-button*]]
[app.main.ui.ds.foundations.assets.icon :refer [icon*]]
[app.main.ui.ds.layout.tab-switcher :refer [tab-switcher*]]
+ [app.main.ui.hooks :as hooks]
[app.main.ui.hooks.resize :refer [use-resize-hook]]
[app.main.ui.workspace.comments :refer [comments-sidebar*]]
- [app.main.ui.workspace.left-header :refer [left-header]]
+ [app.main.ui.workspace.left-header :refer [left-header*]]
[app.main.ui.workspace.right-header :refer [right-header*]]
- [app.main.ui.workspace.sidebar.assets :refer [assets-toolbox]]
- [app.main.ui.workspace.sidebar.debug :refer [debug-panel]]
- [app.main.ui.workspace.sidebar.debug-shape-info :refer [debug-shape-info]]
+ [app.main.ui.workspace.sidebar.assets :refer [assets-toolbox*]]
+ [app.main.ui.workspace.sidebar.debug :refer [debug-panel*]]
+ [app.main.ui.workspace.sidebar.debug-shape-info :refer [debug-shape-info*]]
[app.main.ui.workspace.sidebar.history :refer [history-toolbox*]]
- [app.main.ui.workspace.sidebar.layers :refer [layers-toolbox]]
+ [app.main.ui.workspace.sidebar.layers :refer [layers-toolbox*]]
[app.main.ui.workspace.sidebar.options :refer [options-toolbox*]]
- [app.main.ui.workspace.sidebar.shortcuts :refer [shortcuts-container]]
- [app.main.ui.workspace.sidebar.sitemap :refer [sitemap]]
+ [app.main.ui.workspace.sidebar.shortcuts :refer [shortcuts-container*]]
+ [app.main.ui.workspace.sidebar.sitemap :refer [sitemap*]]
[app.main.ui.workspace.sidebar.versions :refer [versions-toolbox*]]
[app.main.ui.workspace.tokens.sidebar :refer [tokens-sidebar-tab*]]
[app.util.debug :as dbg]
@@ -40,20 +41,61 @@
;; --- Left Sidebar (Component)
-(mf/defc collapse-button
- {::mf/wrap [mf/memo]
- ::mf/wrap-props false}
- [{:keys [on-click] :as props}]
+(defn- on-collapse-left-sidebar
+ []
+ (st/emit! (dw/toggle-layout-flag :collapse-left-sidebar)))
+
+(mf/defc collapse-button*
+ []
;; NOTE: This custom button may be replace by an action button when this variant is designed
[:button {:class (stl/css :collapse-sidebar-button)
- :on-click on-click}
+ :on-click on-collapse-left-sidebar}
[:> icon* {:icon-id "arrow"
:size "s"
:aria-label (tr "workspace.sidebar.collapse")}]])
+(mf/defc layers-content*
+ {::mf/private true
+ ::mf/memo true}
+ [{:keys [width layout]}]
+ (let [{on-pointer-down :on-pointer-down
+ on-lost-pointer-capture :on-lost-pointer-capture
+ on-pointer-move :on-pointer-move
+ height :size}
+ (use-resize-hook :sitemap 200 38 "0.6" :y false nil)
+
+ sitemap-collapsed*
+ (hooks/use-persisted-state ::sitemap-collapsed false)
+
+ sitemap-collapsed?
+ (deref sitemap-collapsed*)
+
+ on-toggle-sitemap-collapsed
+ (mf/use-fn #(reset! sitemap-collapsed* not))
+
+ sitemap-height
+ (if sitemap-collapsed? 32 height)]
+
+ [:article {:class (stl/css :layers-tab)
+ :style {:--height (dm/str height "px")}}
+
+ [:> sitemap* {:layout layout
+ :height sitemap-height
+ :collapsed sitemap-collapsed?
+ :on-toggle-collapsed on-toggle-sitemap-collapsed}]
+
+ (when-not ^boolean sitemap-collapsed?
+ [:div {:class (stl/css :resize-area-horiz)
+ :on-pointer-down on-pointer-down
+ :on-lost-pointer-capture on-lost-pointer-capture
+ :on-pointer-move on-pointer-move}
+
+ [:div {:class (stl/css :resize-handle-horiz)}]])
+
+ [:> layers-toolbox* {:size-parent width}]]))
+
(mf/defc left-sidebar*
- {::mf/wrap [mf/memo]
- ::mf/props :obj}
+ {::mf/memo true}
[{:keys [layout file page-id] :as props}]
(let [options-mode (mf/deref refs/options-mode-global)
project (mf/deref refs/project)
@@ -73,93 +115,53 @@
on-lost-pointer-capture :on-lost-pointer-capture
on-pointer-move :on-pointer-move
parent-ref :parent-ref
- size :size}
+ width :size}
(use-resize-hook :left-sidebar 318 318 500 :x false :left)
- {on-pointer-down-pages :on-pointer-down
- on-lost-pointer-capture-pages :on-lost-pointer-capture
- on-pointer-move-pages :on-pointer-move
- size-pages-opened :size}
- (use-resize-hook :sitemap 200 38 "0.6" :y false nil)
-
- show-pages? (mf/use-state true)
- toggle-pages (mf/use-fn #(reset! show-pages? not))
- size-pages (mf/with-memo [show-pages? size-pages-opened]
- (if @show-pages? size-pages-opened 32))
-
- handle-collapse
- (mf/use-fn #(st/emit! (dw/toggle-layout-flag :collapse-left-sidebar)))
-
on-tab-change
(mf/use-fn
(fn [id]
+ (st/emit! (dcm/go-to-workspace :layout (keyword id)))
(when (= id "tokens")
- (st/emit! (ptk/event ::ev/event {::ev/name "open-tokens-tab"})))
- (st/emit! (dcm/go-to-workspace :layout (keyword id)))))
-
- layers-tab
- (mf/html
- [:article {:class (stl/css :layers-tab)
- :style #js {"--height" (str size-pages "px")}}
-
- [:& sitemap {:layout layout
- :toggle-pages toggle-pages
- :show-pages? @show-pages?
- :size size-pages}]
-
- (when @show-pages?
- [:div {:class (stl/css :resize-area-horiz)
- :on-pointer-down on-pointer-down-pages
- :on-lost-pointer-capture on-lost-pointer-capture-pages
- :on-pointer-move on-pointer-move-pages}
-
- [:div {:class (stl/css :resize-handle-horiz)}]])
-
- [:& layers-toolbox {:size-parent size
- :size size-pages}]])
-
-
- assets-tab
- (mf/html [:& assets-toolbox {:size (- size 58) :file-id file-id}])
-
- tokens-tab
- (when design-tokens?
- (mf/html [:> tokens-sidebar-tab*]))
+ (st/emit! (ptk/event ::ev/event {::ev/name "open-tokens-tab"})))))
tabs
- (if ^boolean mode-inspect?
- #js [#js {:label (tr "workspace.sidebar.layers")
- :id "layers"
- :content layers-tab}]
- (if ^boolean design-tokens?
- #js [#js {:label (tr "workspace.sidebar.layers")
- :id "layers"
- :content layers-tab}
- #js {:label (tr "workspace.toolbar.assets")
- :id "assets"
- :content assets-tab}
- #js {:label "Tokens"
- :id "tokens"
- :content tokens-tab}]
- #js [#js {:label (tr "workspace.sidebar.layers")
- :id "layers"
- :content layers-tab}
- #js {:label (tr "workspace.toolbar.assets")
- :id "assets"
- :content assets-tab}]))]
+ (mf/with-memo [mode-inspect? design-tokens?]
+ (if ^boolean mode-inspect?
+ [{:label (tr "workspace.sidebar.layers")
+ :id "layers"}]
+ (if ^boolean design-tokens?
+ [{:label (tr "workspace.sidebar.layers")
+ :id "layers"}
+ {:label (tr "workspace.toolbar.assets")
+ :id "assets"}
+ {:label "Tokens"
+ :id "tokens"}]
+ [{:label (tr "workspace.sidebar.layers")
+ :id "layers"}
+ {:label (tr "workspace.toolbar.assets")
+ :id "assets"}])))
- [:& (mf/provider muc/sidebar) {:value :left}
+ aside-class
+ (stl/css-case
+ :left-settings-bar true
+ :global/two-row (<= width 300)
+ :global/three-row (and (> width 300) (<= width 400))
+ :global/four-row (> width 400))
+
+ tabs-action-button
+ (mf/with-memo []
+ (mf/html [:> collapse-button* {}]))]
+
+ [:> (mf/provider muc/sidebar) {:value :left}
[:aside {:ref parent-ref
:id "left-sidebar-aside"
:data-testid "left-sidebar"
- :data-size (str size)
- :class (stl/css-case :left-settings-bar true
- :global/two-row (<= size 300)
- :global/three-row (and (> size 300) (<= size 400))
- :global/four-row (> size 400))
- :style #js {"--width" (dm/str size "px")}}
+ :data-size (str width)
+ :class aside-class
+ :style {:--width (dm/str width "px")}}
- [:& left-header
+ [:> left-header*
{:file file
:layout layout
:project project
@@ -170,31 +172,92 @@
:on-lost-pointer-capture on-lost-pointer-capture
:on-pointer-move on-pointer-move
:class (stl/css :resize-area)}]
+
(cond
(true? shortcuts?)
- [:& shortcuts-container {:class (stl/css :settings-bar-content)}]
+ [:> shortcuts-container* {:class (stl/css :settings-bar-content)}]
(true? show-debug?)
- [:& debug-panel {:class (stl/css :settings-bar-content)}]
+ [:> debug-panel* {:class (stl/css :settings-bar-content)}]
:else
[:div {:class (stl/css :settings-bar-content)}
[:> tab-switcher* {:tabs tabs
- :default-selected "layers"
+ :default "layers"
:selected (name section)
- :on-change-tab on-tab-change
+ :on-change on-tab-change
:class (stl/css :left-sidebar-tabs)
:action-button-position "start"
- :action-button (mf/html [:& collapse-button {:on-click handle-collapse}])}]])]]))
+ :action-button tabs-action-button}
+
+ (case section
+ :assets
+ [:> assets-toolbox*
+ {:size (- width 58)
+ :file-id file-id}]
+
+ :tokens
+ [:> tokens-sidebar-tab*]
+
+ :layers
+ [:> layers-content*
+ {:layout layout
+ :width width}])]])]]))
;; --- Right Sidebar (Component)
-(mf/defc right-sidebar*
- {::mf/wrap [mf/memo]}
- [{:keys [layout section file page-id] :as props}]
- (let [drawing-tool (:tool (mf/deref refs/workspace-drawing))
+(defn- on-close-document-history
+ []
+ (st/emit! (dw/remove-layout-flag :document-history)))
- is-comments? (= drawing-tool :comments)
+(mf/defc history-content*
+ {::mf/private true
+ ::mf/memo true}
+ []
+ (let [selected*
+ (hooks/use-persisted-state ::history-sidebar "history")
+
+ selected
+ (deref selected*)
+
+ on-change-tab
+ (mf/use-fn #(reset! selected* %))
+
+ tabs
+ (mf/with-memo []
+ [{:label (tr "workspace.versions.tab.history")
+ :id "history"}
+ {:label (tr "workspace.versions.tab.actions")
+ :id "actions"}])
+
+ button
+ (mf/with-memo []
+ (mf/html
+ [:> icon-button* {:variant "ghost"
+ :aria-label (tr "labels.close")
+ :on-click on-close-document-history
+ :icon "close"}]))]
+
+ [:> tab-switcher* {:tabs tabs
+ :selected selected
+ :on-change on-change-tab
+ :class (stl/css :left-sidebar-tabs)
+ :action-button-position "end"
+ :action-button button}
+
+ (case selected
+ "history"
+ [:article {:class (stl/css :history-tab)}
+ [:> versions-toolbox* {}]]
+
+ "actions"
+ [:article {:class (stl/css :versions-tab)}
+ [:> history-toolbox*]])]))
+
+(mf/defc right-sidebar*
+ {::mf/memo true}
+ [{:keys [layout section file page-id drawing-tool] :as props}]
+ (let [is-comments? (= drawing-tool :comments)
is-history? (contains? layout :document-history)
is-inspect? (= section :inspect)
@@ -210,38 +273,36 @@
is-inspect?
(= current-section :code)))
- {:keys [on-pointer-down on-lost-pointer-capture on-pointer-move set-size size]}
+ {on-pointer-down :on-pointer-down
+ on-lost-pointer-capture :on-lost-pointer-capture
+ on-pointer-move :on-pointer-move
+ set-width :set-size
+ width :size}
(use-resize-hook :code sidebar-default-width sidebar-default-width sidebar-default-max-width :x true :right)
on-change-section
- (mf/use-fn
- (fn [section]
- (reset! current-section* section)))
-
- on-close-history
- (mf/use-fn #(st/emit! (dw/remove-layout-flag :document-history)))
+ (mf/use-fn #(reset! current-section* %))
on-expand
(mf/use-fn
- (mf/deps size)
+ (mf/deps width set-width)
(fn []
- (set-size (if (> size sidebar-default-width) sidebar-default-width sidebar-default-max-width))))
-
- props
- (mf/spread-props props
- {:on-change-section on-change-section
- :on-expand on-expand})]
+ (set-width (if (> width sidebar-default-width)
+ sidebar-default-width
+ sidebar-default-max-width))))]
[:> (mf/provider muc/sidebar) {:value :right}
[:aside
{:class (stl/css-case :right-settings-bar true
:not-expand (not can-be-expanded?)
- :expanded (> size sidebar-default-width))
+ :expanded (> width sidebar-default-width))
:id "right-sidebar-aside"
:data-testid "right-sidebar"
- :data-size (str size)
- :style {"--width" (if can-be-expanded? (dm/str size "px") (dm/str sidebar-default-width "px"))}}
+ :data-size (str width)
+ :style {:--width (if can-be-expanded?
+ (dm/str width "px")
+ (dm/str sidebar-default-width "px"))}}
(when can-be-expanded?
[:div {:class (stl/css :resize-area)
@@ -257,42 +318,16 @@
[:div {:class (stl/css :settings-bar-inside)}
(cond
dbg-shape-panel?
- [:& debug-shape-info]
+ [:> debug-shape-info*]
is-comments?
[:> comments-sidebar* {}]
is-history?
- (let [history-tab
- (mf/html
- [:article {:class (stl/css :history-tab)}
- [:> history-toolbox*]])
-
- versions-tab
- (mf/html
- [:article {:class (stl/css :versions-tab)}
- [:> versions-toolbox*]])
-
- button
- (mf/html
- [:> icon-button* {:variant "ghost"
- :aria-label (tr "labels.close")
- :on-click on-close-history
- :icon "close"}])
- tabs (mf/object
- [{:label (tr "workspace.versions.tab.history")
- :id "history"
- :content versions-tab}
- {:label (tr "workspace.versions.tab.actions")
- :id "actions"
- :content history-tab}])]
-
- [:> tab-switcher*
- {:tabs tabs
- :default-selected "history"
- :class (stl/css :left-sidebar-tabs)
- :action-button-position "end"
- :action-button button}])
+ [:> history-content* {}]
:else
- [:> options-toolbox* props])]]]))
+ (let [props (mf/spread-props props
+ {:on-change-section on-change-section
+ :on-expand on-expand})]
+ [:> options-toolbox* props]))]]]))
diff --git a/frontend/src/app/main/ui/workspace/sidebar/assets.cljs b/frontend/src/app/main/ui/workspace/sidebar/assets.cljs
index 466715292b..9237b5acea 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/assets.cljs
+++ b/frontend/src/app/main/ui/workspace/sidebar/assets.cljs
@@ -71,9 +71,8 @@
[v [a b]]
(if (= v a) b a))
-(mf/defc assets-toolbox
- {::mf/wrap [mf/memo]
- ::mf/wrap-props false}
+(mf/defc assets-toolbox*
+ {::mf/wrap [mf/memo]}
[{:keys [size file-id]}]
(let [read-only? (mf/use-ctx ctx/workspace-read-only?)
filters* (mf/use-state
diff --git a/frontend/src/app/main/ui/workspace/sidebar/debug.cljs b/frontend/src/app/main/ui/workspace/sidebar/debug.cljs
index 4c6a715b23..27c3fcb7df 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/debug.cljs
+++ b/frontend/src/app/main/ui/workspace/sidebar/debug.cljs
@@ -18,8 +18,8 @@
[app.util.i18n :as i18n :refer [tr]]
[rumext.v2 :as mf]))
-(mf/defc debug-panel
- [{:keys [class] :as props}]
+(mf/defc debug-panel*
+ [{:keys [class]}]
(let [on-toggle-enabled
(mf/use-fn
(fn [event option]
diff --git a/frontend/src/app/main/ui/workspace/sidebar/debug_shape_info.cljs b/frontend/src/app/main/ui/workspace/sidebar/debug_shape_info.cljs
index 12745448f5..b82adabff3 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/debug_shape_info.cljs
+++ b/frontend/src/app/main/ui/workspace/sidebar/debug_shape_info.cljs
@@ -118,9 +118,9 @@
[:div {:class (stl/css :attrs-container-value)} (str value)]))
-(mf/defc debug-shape-info
+(mf/defc debug-shape-info*
[]
- (let [objects (mf/deref refs/workspace-page-objects)
+ (let [objects (mf/deref refs/workspace-page-objects)
selected (->> (mf/deref refs/selected-shapes)
(map (d/getf objects)))]
diff --git a/frontend/src/app/main/ui/workspace/sidebar/layers.cljs b/frontend/src/app/main/ui/workspace/sidebar/layers.cljs
index a1a88c05dd..eb4537dd10 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/layers.cljs
+++ b/frontend/src/app/main/ui/workspace/sidebar/layers.cljs
@@ -475,9 +475,8 @@
(dom/add-class! last-hidden-frame "sticky"))))))
-(mf/defc layers-toolbox
- {::mf/wrap [mf/memo]
- ::mf/wrap-props false}
+(mf/defc layers-toolbox*
+ {::mf/wrap [mf/memo]}
[{:keys [size-parent]}]
(let [page (mf/deref refs/workspace-page)
focus (mf/deref refs/workspace-focus-selected)
diff --git a/frontend/src/app/main/ui/workspace/sidebar/options.cljs b/frontend/src/app/main/ui/workspace/sidebar/options.cljs
index dfe86f6a8d..1ebc0fd53a 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/options.cljs
+++ b/frontend/src/app/main/ui/workspace/sidebar/options.cljs
@@ -134,6 +134,7 @@
:file-id file-id
:libraries libraries}])]))
+;; FIXME: need optimizations
(mf/defc options-content*
{::mf/memo true
::mf/private true}
@@ -155,59 +156,47 @@
(st/emit! :interrupt (dwc/set-workspace-read-only true))
(st/emit! :interrupt (dwc/set-workspace-read-only false)))))
- design-content
- (mf/html [:> design-menu*
- {:selected selected
- :objects objects
- :page-id page-id
- :file-id file-id
- :selected-shapes selected-shapes
- :shapes-with-children shapes-with-children}])
-
- inspect-content
- (mf/html [:div {:class (stl/css :element-options :inspect-options)}
- [:& hrs/right-sidebar {:page-id page-id
- :objects objects
- :file-id file-id
- :frame shape-parent-frame
- :shapes selected-shapes
- :on-change-section on-change-section
- :on-expand on-expand
- :from :workspace}]])
-
- interactions-content
- (mf/html [:div {:class (stl/css :element-options :interaction-options)}
- [:& interactions-menu {:shape (first shapes)}]])
-
-
tabs
- (if (:can-edit permissions)
- #js [#js {:label (tr "workspace.options.design")
- :id "design"
- :content design-content}
-
- #js {:label (tr "workspace.options.prototype")
- :id "prototype"
- :content interactions-content}
-
- #js {:label (tr "workspace.options.inspect")
- :id "inspect"
- :content inspect-content}]
- #js [#js {:label (tr "workspace.options.inspect")
- :id "inspect"
- :content inspect-content}])]
+ (mf/with-memo []
+ [{:label (tr "workspace.options.design")
+ :id "design"}
+ {:label (tr "workspace.options.prototype")
+ :id "prototype"}
+ {:label (tr "workspace.options.inspect")
+ :id "inspect"}])]
[:div {:class (stl/css :tool-window)}
(if (:can-edit permissions)
[:> tab-switcher* {:tabs tabs
- :default-selected "info"
- :on-change-tab on-change-tab
+ :on-change on-change-tab
:selected (name options-mode)
- :class (stl/css :options-tab-switcher)}]
+ :class (stl/css :options-tab-switcher)}
+ (case options-mode
+ :prototype
+ [:div {:class (stl/css :element-options :interaction-options)}
+ [:& interactions-menu {:shape (first shapes)}]]
- [:div {:class (stl/css-case :element-options true
- :inspect-options true
- :read-only true)}
+ :inspect
+ [:div {:class (stl/css :element-options :inspect-options)}
+ [:& hrs/right-sidebar {:page-id page-id
+ :objects objects
+ :file-id file-id
+ :frame shape-parent-frame
+ :shapes selected-shapes
+ :on-change-section on-change-section
+ :on-expand on-expand
+ :from :workspace}]]
+
+ :design
+ [:> design-menu* {:selected selected
+ :objects objects
+ :page-id page-id
+ :file-id file-id
+ :selected-shapes selected-shapes
+ :shapes-with-children shapes-with-children}])]
+
+ ;; FIXME: Reuse tab???
+ [:div {:class (stl/css :element-options :inspect-options :read-only)}
[:& hrs/right-sidebar {:page-id page-id
:objects objects
:file-id file-id
diff --git a/frontend/src/app/main/ui/workspace/sidebar/shortcuts.cljs b/frontend/src/app/main/ui/workspace/sidebar/shortcuts.cljs
index 093ee37219..23a980b5e9 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/shortcuts.cljs
+++ b/frontend/src/app/main/ui/workspace/sidebar/shortcuts.cljs
@@ -364,8 +364,8 @@
:match-section? match-section?
:filter-term filter-term}]]])))
-(mf/defc shortcuts-container
- [{:keys [class] :as props}]
+(mf/defc shortcuts-container*
+ [{:keys [class]}]
(let [workspace-shortcuts app.main.data.workspace.shortcuts/shortcuts
path-shortcuts app.main.data.workspace.path.shortcuts/shortcuts
all-workspace-shortcuts (->> (d/deep-merge path-shortcuts workspace-shortcuts)
diff --git a/frontend/src/app/main/ui/workspace/sidebar/sitemap.cljs b/frontend/src/app/main/ui/workspace/sidebar/sitemap.cljs
index 99c2886ae8..49ddedff3d 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/sitemap.cljs
+++ b/frontend/src/app/main/ui/workspace/sidebar/sitemap.cljs
@@ -193,8 +193,8 @@
;; --- Pages List
-(mf/defc pages-list
- {::mf/wrap-props false}
+(mf/defc pages-list*
+ {::mf/private true}
[{:keys [file]}]
(let [pages (:pages file)
deletable? (> (count pages) 1)
@@ -213,9 +213,8 @@
;; --- Sitemap Toolbox
-(mf/defc sitemap
- {::mf/wrap-props false}
- [{:keys [size show-pages? toggle-pages]}]
+(mf/defc sitemap*
+ [{:keys [height collapsed on-toggle-collapsed]}]
(let [file (mf/deref ref:file-with-pages)
file-id (get file :id)
project-id (get file :project-id)
@@ -230,11 +229,11 @@
permissions (mf/use-ctx ctx/permissions)]
[:div {:class (stl/css :sitemap)
- :style #js {"--height" (str size "px")}}
+ :style {:--height (dm/str height "px")}}
[:& title-bar {:collapsable true
- :collapsed (not show-pages?)
- :on-collapsed toggle-pages
+ :collapsed collapsed
+ :on-collapsed on-toggle-collapsed
:all-clickable true
:title (tr "workspace.sidebar.sitemap")
:class (stl/css :title-spacing-sitemap)}
@@ -250,5 +249,7 @@
:on-click on-create
:icon "add"}])]
- [:div {:class (stl/css :tool-window-content)}
- [:& pages-list {:file file :key (:id file)}]]]))
+ (when-not ^boolean collapsed
+ [:div {:class (stl/css :tool-window-content)}
+ [:> pages-list* {:file file :key (dm/str (:id file))}]])]))
+
diff --git a/frontend/src/app/main/ui/workspace/tokens/export/modal.cljs b/frontend/src/app/main/ui/workspace/tokens/export/modal.cljs
index 40dd59ae68..432c91f568 100644
--- a/frontend/src/app/main/ui/workspace/tokens/export/modal.cljs
+++ b/frontend/src/app/main/ui/workspace/tokens/export/modal.cljs
@@ -105,31 +105,31 @@
(mf/defc export-modal-body*
{::mf/private true}
[]
- (let [selected-tab (mf/use-state "single-file")
+ (let [selected-tab* (mf/use-state "single")
+ selected-tab (deref selected-tab*)
on-change-tab
- (mf/use-fn
- (fn [tab-id]
- (reset! selected-tab tab-id)))
+ (mf/use-fn #(reset! selected-tab* %))
- single-file-content
- (mf/html [:> single-file-tab*])
-
- multiple-files-content
- (mf/html [:> multi-file-tab*])
-
- tabs #js [#js {:label (tr "workspace.tokens.export.single-file")
- :id "single-file"
- :content single-file-content}
- #js {:label (tr "workspace.tokens.export.multiple-files")
- :id "multiple-files"
- :content multiple-files-content}]]
+ tabs
+ (mf/with-memo []
+ [{:label (tr "workspace.tokens.export.single-file")
+ :id "single"}
+ {:label (tr "workspace.tokens.export.multiple-files")
+ :id "multiple"}])]
[:div {:class (stl/css :export-modal-wrapper)}
- [:> heading* {:level 2 :typography "headline-medium" :class (stl/css :export-modal-title)}
+ [:> heading* {:level 2
+ :typography "headline-medium"
+ :class (stl/css :export-modal-title)}
(tr "workspace.tokens.export-tokens")]
- [:> tab-switcher*
- {:tabs tabs
- :selected @selected-tab
- :on-change-tab on-change-tab}]]))
+ [:> tab-switcher* {:tabs tabs
+ :selected selected-tab
+ :on-change on-change-tab}
+ (case selected-tab
+ "single"
+ [:> single-file-tab* {}]
+
+ "multiple"
+ [:> multi-file-tab* {}])]]))