From 8df780b2378463e40733309eef9b135e8be5dc16 Mon Sep 17 00:00:00 2001 From: Florian Schroedl Date: Mon, 31 Mar 2025 15:21:12 +0200 Subject: [PATCH 1/6] :sparkles: Allow editing of sets in create theme dialog :recycle: theme-state -> current-theme --- .../ui/workspace/tokens/modals/themes.cljs | 163 ++++++++---------- .../ui/workspace/tokens/modals/themes.scss | 1 + 2 files changed, 76 insertions(+), 88 deletions(-) diff --git a/frontend/src/app/main/ui/workspace/tokens/modals/themes.cljs b/frontend/src/app/main/ui/workspace/tokens/modals/themes.cljs index d6f98ff30..33ba86b5b 100644 --- a/frontend/src/app/main/ui/workspace/tokens/modals/themes.cljs +++ b/frontend/src/app/main/ui/workspace/tokens/modals/themes.cljs @@ -241,54 +241,6 @@ :disabled disabled?} (tr "workspace.token.save-theme")]])) -(mf/defc create-theme - [{:keys [set-state]}] - (let [theme (ctob/make-token-theme :name "") - on-back #(set-state (constantly {:type :themes-overview})) - theme-state* (mf/use-state theme) - theme-state (deref theme-state*) - disabled? (-> (:name theme-state) - (str/trim) - (str/empty?)) - - on-change-field - (mf/use-fn - (fn [field value] - (swap! theme-state* #(assoc % field value)))) - - on-save-form - (mf/use-fn - (mf/deps theme-state) - (fn [e] - (dom/prevent-default e) - (let [theme (-> theme-state - (update :name str/trim) - (update :group str/trim) - (update :description str/trim))] - (when-not (str/empty? (:name theme)) - (st/emit! (ptk/event ::ev/event {::ev/name "create-tokens-theme"}) - (wdt/create-token-theme theme))) - (on-back)))) - - close-modal - (mf/use-fn - (fn [e] - (dom/prevent-default e) - (st/emit! (modal/hide))))] - - [:div {:class (stl/css :themes-modal-wrapper)} - [:> heading* {:level 2 :typography "headline-medium" :class (stl/css :themes-modal-title)} - (tr "workspace.token.add-new-theme")] - [:form {:on-submit on-save-form} - [:div {:class (stl/css :create-theme-wrapper)} - [:> theme-inputs* {:theme theme - :on-change-field on-change-field}] - - [:div {:class (stl/css :button-footer)} - [:> theme-modal-buttons* {:close-modal close-modal - :on-save-form on-save-form - :disabled? disabled?}]]]]])) - (defn- make-lib-with-theme [theme sets] (let [tlib (-> (ctob/make-tokens-lib) @@ -296,40 +248,37 @@ tlib (reduce ctob/add-set tlib sets)] (ctob/activate-theme tlib (:group theme) (:name theme)))) -(mf/defc controlled-edit-theme - [{:keys [state set-state]}] - (let [{:keys [theme-path]} @state - [_ theme-group theme-name] theme-path - ordered-token-sets (mf/deref refs/workspace-ordered-token-sets) +(mf/defc edit-create-theme + [{:keys [set-state theme on-save edit-theme?]}] + (let [ordered-token-sets (mf/deref refs/workspace-ordered-token-sets) token-sets (mf/deref refs/workspace-token-sets-tree) - theme (mf/deref (refs/workspace-token-theme theme-group theme-name)) - theme-state* (mf/use-state theme) - theme-state (deref theme-state*) - lib (make-lib-with-theme theme-state ordered-token-sets) + current-theme* (mf/use-state theme) + current-theme (deref current-theme*) + lib (make-lib-with-theme current-theme ordered-token-sets) ;; Form / Modal handlers on-back #(set-state (constantly {:type :themes-overview})) - disabled? (-> (:name theme-state) + disabled? (-> (:name current-theme) (str/trim) (str/empty?)) on-change-field (mf/use-fn (fn [field value] - (swap! theme-state* #(assoc % field value)))) + (swap! current-theme* #(assoc % field value)))) on-save-form (mf/use-fn - (mf/deps theme theme-state) + (mf/deps current-theme on-save on-back) (fn [e] (dom/prevent-default e) - (let [theme' (-> theme-state + (let [theme' (-> current-theme (update :name str/trim) (update :group str/trim) (update :description str/trim))] - (when-not (str/empty? (:name theme)) - (st/emit! (wdt/update-token-theme [(:group theme) (:name theme)] theme'))) + (when-not (str/empty? (:name theme')) + (on-save theme')) (on-back)))) close-modal @@ -338,39 +287,39 @@ (dom/prevent-default e) (st/emit! (modal/hide)))) - on-delete-token + on-delete-theme (mf/use-fn - (mf/deps theme on-back) + (mf/deps current-theme on-back) (fn [] - (st/emit! (wdt/delete-token-theme (:group theme) (:name theme))) + (st/emit! (wdt/delete-token-theme (:group current-theme) (:name current-theme))) (on-back))) ;; Sets tree handlers token-set-group-active? (mf/use-fn - (mf/deps theme-state) + (mf/deps current-theme) (fn [group-path] (ctob/sets-at-path-all-active? lib group-path))) token-set-active? (mf/use-fn - (mf/deps theme-state) + (mf/deps current-theme) (fn [name] - (contains? (:sets theme-state) name))) + (contains? (:sets current-theme) name))) on-toggle-token-set (mf/use-fn - (mf/deps theme-state) + (mf/deps current-theme) (fn [set-name] - (swap! theme-state* #(ctob/toggle-set % set-name)))) + (swap! current-theme* #(ctob/toggle-set % set-name)))) on-toggle-token-set-group (mf/use-fn - (mf/deps theme-state ordered-token-sets) + (mf/deps current-theme ordered-token-sets) (fn [group-path] - (swap! theme-state* (fn [theme'] - (let [lib' (make-lib-with-theme theme' ordered-token-sets)] - (clt/toggle-token-set-group group-path lib' theme')))))) + (swap! current-theme* (fn [theme'] + (let [lib' (make-lib-with-theme theme' ordered-token-sets)] + (clt/toggle-token-set-group group-path lib' theme')))))) on-click-token-set (mf/use-fn @@ -381,17 +330,20 @@ [:div {:class (stl/css :themes-modal-wrapper)} [:> heading* {:level 2 :typography "headline-medium" :class (stl/css :themes-modal-title)} - (tr "workspace.token.edit-theme-title")] + (if edit-theme? + (tr "workspace.token.edit-theme-title") + (tr "workspace.token.add-new-theme"))] [:form {:on-submit on-save-form :class (stl/css :edit-theme-form)} [:div {:class (stl/css :edit-theme-wrapper)} - [:button {:on-click on-back - :class (stl/css :back-btn) - :type "button"} - [:> icon* {:icon-id ic/arrow-left :aria-hidden true}] - (tr "workspace.token.back-to-themes")] + (when edit-theme? + [:button {:on-click on-back + :class (stl/css :back-btn) + :type "button"} + [:> icon* {:icon-id ic/arrow-left :aria-hidden true}] + (tr "workspace.token.back-to-themes")]) - [:> theme-inputs* {:theme theme + [:> theme-inputs* {:theme current-theme :on-change-field on-change-field}] [:> text* {:as "span" :typography "body-small" :class (stl/css :select-sets-message)} (tr "workspace.token.set-selection-theme")] @@ -408,16 +360,51 @@ :origin "theme-modal"}]] [:div {:class (stl/css :edit-theme-footer)} - [:> button* {:variant "secondary" - :type "button" - :icon "delete" - :on-click on-delete-token} - (tr "labels.delete")] + (when edit-theme? + [:> button* {:variant "secondary" + :type "button" + :icon "delete" + :on-click on-delete-theme} + (tr "labels.delete")]) [:div {:class (stl/css :button-footer)} [:> theme-modal-buttons* {:close-modal close-modal :on-save-form on-save-form :disabled? disabled?}]]]]]])) +(mf/defc edit-theme + [{:keys [state set-state]}] + (let [{:keys [theme-path]} @state + [_ theme-group theme-name] theme-path + theme (mf/deref (refs/workspace-token-theme theme-group theme-name)) + + on-save + (mf/use-fn + (mf/deps theme) + (fn [theme'] + (st/emit! (wdt/update-token-theme [(:group theme) (:name theme)] theme'))))] + + [:& edit-create-theme + {:set-state set-state + :theme theme + :on-save on-save + :edit-theme? true}])) + +(mf/defc create-theme + [{:keys [set-state]}] + (let [theme (ctob/make-token-theme :name "") + + on-save + (mf/use-fn + (fn [theme] + (st/emit! (ptk/event ::ev/event {::ev/name "create-tokens-theme"}) + (wdt/create-token-theme theme))))] + + [:& edit-create-theme + {:set-state set-state + :theme theme + :on-save on-save + :create-theme? true}])) + (mf/defc themes-modal-body* {::mf/private true} [] @@ -429,7 +416,7 @@ component (case (:type @state) :empty-themes empty-themes :themes-overview (if (empty? themes) empty-themes themes-overview) - :edit-theme controlled-edit-theme + :edit-theme edit-theme :create-theme create-theme)] [:& component {:state state :set-state set-state}])) diff --git a/frontend/src/app/main/ui/workspace/tokens/modals/themes.scss b/frontend/src/app/main/ui/workspace/tokens/modals/themes.scss index 9277b720b..59c1dae94 100644 --- a/frontend/src/app/main/ui/workspace/tokens/modals/themes.scss +++ b/frontend/src/app/main/ui/workspace/tokens/modals/themes.scss @@ -68,6 +68,7 @@ .button-footer { display: flex; + margin-left: auto; justify-content: flex-end; gap: $s-6; } From 215fb53c520a65a580aa412793aa5f839ce2b508 Mon Sep 17 00:00:00 2001 From: Florian Schroedl Date: Tue, 1 Apr 2025 14:46:49 +0200 Subject: [PATCH 2/6] :construction: Use use-fn --- frontend/src/app/main/ui/workspace/tokens/modals/themes.cljs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/app/main/ui/workspace/tokens/modals/themes.cljs b/frontend/src/app/main/ui/workspace/tokens/modals/themes.cljs index 33ba86b5b..eaf6763fc 100644 --- a/frontend/src/app/main/ui/workspace/tokens/modals/themes.cljs +++ b/frontend/src/app/main/ui/workspace/tokens/modals/themes.cljs @@ -258,7 +258,7 @@ lib (make-lib-with-theme current-theme ordered-token-sets) ;; Form / Modal handlers - on-back #(set-state (constantly {:type :themes-overview})) + on-back (mf/use-fn #(set-state (constantly {:type :themes-overview}))) disabled? (-> (:name current-theme) (str/trim) (str/empty?)) From c1165bd12deb112e8f83c536b8e99edda9ae2061 Mon Sep 17 00:00:00 2001 From: Florian Schroedl Date: Tue, 1 Apr 2025 14:48:02 +0200 Subject: [PATCH 3/6] :construction: Convert rumext --- .../ui/workspace/tokens/modals/themes.cljs | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/frontend/src/app/main/ui/workspace/tokens/modals/themes.cljs b/frontend/src/app/main/ui/workspace/tokens/modals/themes.cljs index eaf6763fc..e7cf659d7 100644 --- a/frontend/src/app/main/ui/workspace/tokens/modals/themes.cljs +++ b/frontend/src/app/main/ui/workspace/tokens/modals/themes.cljs @@ -248,8 +248,8 @@ tlib (reduce ctob/add-set tlib sets)] (ctob/activate-theme tlib (:group theme) (:name theme)))) -(mf/defc edit-create-theme - [{:keys [set-state theme on-save edit-theme?]}] +(mf/defc edit-create-theme* + [{:keys [set-state theme on-save is-editing]}] (let [ordered-token-sets (mf/deref refs/workspace-ordered-token-sets) token-sets (mf/deref refs/workspace-token-sets-tree) @@ -330,13 +330,13 @@ [:div {:class (stl/css :themes-modal-wrapper)} [:> heading* {:level 2 :typography "headline-medium" :class (stl/css :themes-modal-title)} - (if edit-theme? + (if is-editing (tr "workspace.token.edit-theme-title") (tr "workspace.token.add-new-theme"))] [:form {:on-submit on-save-form :class (stl/css :edit-theme-form)} [:div {:class (stl/css :edit-theme-wrapper)} - (when edit-theme? + (when is-editing [:button {:on-click on-back :class (stl/css :back-btn) :type "button"} @@ -360,7 +360,7 @@ :origin "theme-modal"}]] [:div {:class (stl/css :edit-theme-footer)} - (when edit-theme? + (when is-editing [:> button* {:variant "secondary" :type "button" :icon "delete" @@ -383,11 +383,11 @@ (fn [theme'] (st/emit! (wdt/update-token-theme [(:group theme) (:name theme)] theme'))))] - [:& edit-create-theme + [:> edit-create-theme* {:set-state set-state :theme theme :on-save on-save - :edit-theme? true}])) + :is-editing true}])) (mf/defc create-theme [{:keys [set-state]}] @@ -399,11 +399,10 @@ (st/emit! (ptk/event ::ev/event {::ev/name "create-tokens-theme"}) (wdt/create-token-theme theme))))] - [:& edit-create-theme + [:> edit-create-theme* {:set-state set-state :theme theme - :on-save on-save - :create-theme? true}])) + :on-save on-save}])) (mf/defc themes-modal-body* {::mf/private true} From 12f72c8ca90b10dc1b583544613c2713ea8e9e36 Mon Sep 17 00:00:00 2001 From: Florian Schroedl Date: Thu, 3 Apr 2025 10:32:30 +0200 Subject: [PATCH 4/6] :construction: Show back button only when coming from a modal view --- .../ui/workspace/tokens/modals/themes.cljs | 61 +++++++++++-------- 1 file changed, 37 insertions(+), 24 deletions(-) diff --git a/frontend/src/app/main/ui/workspace/tokens/modals/themes.cljs b/frontend/src/app/main/ui/workspace/tokens/modals/themes.cljs index e7cf659d7..2eae38625 100644 --- a/frontend/src/app/main/ui/workspace/tokens/modals/themes.cljs +++ b/frontend/src/app/main/ui/workspace/tokens/modals/themes.cljs @@ -33,11 +33,11 @@ [rumext.v2 :as mf])) (mf/defc empty-themes - [{:keys [set-state]}] + [{:keys [change-view]}] (let [create-theme (mf/use-fn - (mf/deps set-state) - #(set-state (fn [_] {:type :create-theme}))) + (mf/deps change-view) + #(change-view :create-theme)) close-modal (mf/use-fn #(st/emit! (modal/hide)))] @@ -78,17 +78,17 @@ :label ""}]])) (mf/defc themes-overview - [{:keys [set-state]}] + [{:keys [change-view]}] (let [active-theme-ids (mf/deref refs/workspace-active-theme-paths) themes-groups (mf/deref refs/workspace-token-theme-tree-no-hidden) create-theme (mf/use-fn - (mf/deps set-state) + (mf/deps change-view) (fn [e] (dom/prevent-default e) (dom/stop-propagation e) - (set-state (fn [_] {:type :create-theme})))) + (change-view :create-theme))) close-modal (mf/use-fn @@ -122,8 +122,7 @@ (fn [e] (dom/prevent-default e) (dom/stop-propagation e) - (set-state (fn [_] {:type :edit-theme - :theme-path [(:id theme) (:group theme) (:name theme)]})))]] + (change-view :edit-theme {:theme-path [(:id theme) (:group theme) (:name theme)]}))]] [:li {:key theme-id :class (stl/css :theme-row)} [:div {:class (stl/css :theme-switch-row)} @@ -249,7 +248,7 @@ (ctob/activate-theme tlib (:group theme) (:name theme)))) (mf/defc edit-create-theme* - [{:keys [set-state theme on-save is-editing]}] + [{:keys [state change-view theme on-save is-editing]}] (let [ordered-token-sets (mf/deref refs/workspace-ordered-token-sets) token-sets (mf/deref refs/workspace-token-sets-tree) @@ -257,8 +256,12 @@ current-theme (deref current-theme*) lib (make-lib-with-theme current-theme ordered-token-sets) + has-back-button? (contains? #{:empty-themes :themes-overview} (:prev-type state)) + ;; Form / Modal handlers - on-back (mf/use-fn #(set-state (constantly {:type :themes-overview}))) + on-back (mf/use-fn + (mf/deps change-view) + #(change-view :themes-overview)) disabled? (-> (:name current-theme) (str/trim) (str/empty?)) @@ -336,7 +339,7 @@ [:form {:on-submit on-save-form :class (stl/css :edit-theme-form)} [:div {:class (stl/css :edit-theme-wrapper)} - (when is-editing + (when has-back-button? [:button {:on-click on-back :class (stl/css :back-btn) :type "button"} @@ -372,8 +375,8 @@ :disabled? disabled?}]]]]]])) (mf/defc edit-theme - [{:keys [state set-state]}] - (let [{:keys [theme-path]} @state + [{:keys [state change-view]}] + (let [{:keys [theme-path]} state [_ theme-group theme-name] theme-path theme (mf/deref (refs/workspace-token-theme theme-group theme-name)) @@ -384,15 +387,15 @@ (st/emit! (wdt/update-token-theme [(:group theme) (:name theme)] theme'))))] [:> edit-create-theme* - {:set-state set-state + {:state state + :change-view change-view :theme theme :on-save on-save :is-editing true}])) (mf/defc create-theme - [{:keys [set-state]}] + [{:keys [state change-view]}] (let [theme (ctob/make-token-theme :name "") - on-save (mf/use-fn (fn [theme] @@ -400,25 +403,35 @@ (wdt/create-token-theme theme))))] [:> edit-create-theme* - {:set-state set-state + {:state state + :change-view change-view :theme theme :on-save on-save}])) (mf/defc themes-modal-body* {::mf/private true} [] - (let [themes (mf/deref refs/workspace-token-themes-no-hidden) - state (mf/use-state #(if (empty? themes) - {:type :create-theme} - {:type :themes-overview})) - set-state (mf/use-fn #(swap! state %)) - component (case (:type @state) + (let [themes (mf/deref refs/workspace-token-themes-no-hidden) + state* (mf/use-state #(if (empty? themes) + {:type :create-theme} + {:type :themes-overview})) + state (deref state*) + + change-view (mf/use-fn + (fn [type & [state']] + (swap! state* (fn [current-state] + (merge + {:type type + :prev-type (:type current-state)} + state'))))) + + component (case (:type state) :empty-themes empty-themes :themes-overview (if (empty? themes) empty-themes themes-overview) :edit-theme edit-theme :create-theme create-theme)] [:& component {:state state - :set-state set-state}])) + :change-view change-view}])) (mf/defc token-themes-modal {::mf/wrap-props false From 1c209f49fc0f3e028f44dfa6f95d3f1454c5d883 Mon Sep 17 00:00:00 2001 From: Florian Schroedl Date: Mon, 7 Apr 2025 16:36:02 +0200 Subject: [PATCH 5/6] :construction: Don't expose state --- .../ui/workspace/tokens/modals/themes.cljs | 25 +++++++++++-------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/frontend/src/app/main/ui/workspace/tokens/modals/themes.cljs b/frontend/src/app/main/ui/workspace/tokens/modals/themes.cljs index 2eae38625..a132495e3 100644 --- a/frontend/src/app/main/ui/workspace/tokens/modals/themes.cljs +++ b/frontend/src/app/main/ui/workspace/tokens/modals/themes.cljs @@ -248,7 +248,7 @@ (ctob/activate-theme tlib (:group theme) (:name theme)))) (mf/defc edit-create-theme* - [{:keys [state change-view theme on-save is-editing]}] + [{:keys [change-view theme on-save is-editing has-prev-view]}] (let [ordered-token-sets (mf/deref refs/workspace-ordered-token-sets) token-sets (mf/deref refs/workspace-token-sets-tree) @@ -256,8 +256,6 @@ current-theme (deref current-theme*) lib (make-lib-with-theme current-theme ordered-token-sets) - has-back-button? (contains? #{:empty-themes :themes-overview} (:prev-type state)) - ;; Form / Modal handlers on-back (mf/use-fn (mf/deps change-view) @@ -339,7 +337,7 @@ [:form {:on-submit on-save-form :class (stl/css :edit-theme-form)} [:div {:class (stl/css :edit-theme-wrapper)} - (when has-back-button? + (when has-prev-view [:button {:on-click on-back :class (stl/css :back-btn) :type "button"} @@ -374,11 +372,15 @@ :on-save-form on-save-form :disabled? disabled?}]]]]]])) +(defn has-prev-view [prev-view-type] + (contains? #{:empty-themes :themes-overview} prev-view-type)) + (mf/defc edit-theme [{:keys [state change-view]}] (let [{:keys [theme-path]} state [_ theme-group theme-name] theme-path theme (mf/deref (refs/workspace-token-theme theme-group theme-name)) + has-prev-view (has-prev-view (:prev-type state)) on-save (mf/use-fn @@ -387,11 +389,11 @@ (st/emit! (wdt/update-token-theme [(:group theme) (:name theme)] theme'))))] [:> edit-create-theme* - {:state state - :change-view change-view + {:change-view change-view :theme theme :on-save on-save - :is-editing true}])) + :is-editing true + :has-prev-view has-prev-view}])) (mf/defc create-theme [{:keys [state change-view]}] @@ -400,13 +402,14 @@ (mf/use-fn (fn [theme] (st/emit! (ptk/event ::ev/event {::ev/name "create-tokens-theme"}) - (wdt/create-token-theme theme))))] + (wdt/create-token-theme theme)))) + has-prev-view (has-prev-view (:prev-type state))] [:> edit-create-theme* - {:state state - :change-view change-view + {:change-view change-view :theme theme - :on-save on-save}])) + :on-save on-save + :has-prev-view has-prev-view}])) (mf/defc themes-modal-body* {::mf/private true} From 0281e0dba45eb38bd443481bcb5e36c4882d8cdd Mon Sep 17 00:00:00 2001 From: Florian Schroedl Date: Mon, 7 Apr 2025 16:42:43 +0200 Subject: [PATCH 6/6] :construction: Explicit state handling --- .../app/main/ui/workspace/tokens/modals/themes.cljs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/frontend/src/app/main/ui/workspace/tokens/modals/themes.cljs b/frontend/src/app/main/ui/workspace/tokens/modals/themes.cljs index a132495e3..9fa2aa968 100644 --- a/frontend/src/app/main/ui/workspace/tokens/modals/themes.cljs +++ b/frontend/src/app/main/ui/workspace/tokens/modals/themes.cljs @@ -421,12 +421,12 @@ state (deref state*) change-view (mf/use-fn - (fn [type & [state']] + (fn [type & {:keys [theme-path]}] (swap! state* (fn [current-state] - (merge - {:type type - :prev-type (:type current-state)} - state'))))) + (cond-> current-state + :always (assoc :type type + :prev-type (:type current-state)) + :theme-path (assoc :theme-path theme-path)))))) component (case (:type state) :empty-themes empty-themes