Repository: penpot/penpot
File: frontend/src/app/main/ui/workspace/tokens/modals/themes.cljs (ClojureScript)

Code before:
         (fn [theme]
           (st/emit! (ptk/event ::ev/event {::ev/name "create-tokens-theme"})
                     (wdt/create-token-theme theme))))]

    [:> edit-create-theme*
     {: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}))
        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
                   :change-view change-view}]))

(mf/defc token-themes-modal
  {::mf/wrap-props false
   ::mf/register modal/components
   ::mf/register-as :tokens/themes}
  []
  [:div {:class (stl/css :modal-overlay)}
   [:div {:class (stl/css :modal-dialog)
          :data-testid "token-theme-update-create-modal"}
    [:> icon-button* {:class (stl/css :close-btn)
                      :on-click modal/hide!
                      :aria-label (tr "labels.close")
                      :variant "action"
                      :icon "close"}]
    [:> themes-modal-body*]]])


Review comment (suggestion):
This is a bit subtle... I don't like the idea that sub components need to know the structure of the state. Instead I'd prefer something like this:

```clojure
        change-view (mf/use-fn
                     (fn [type & {:keys [:theme-path]}]
                       (swap! state* (fn [current-state]
                                       (cond-> current-state
                                         :always
                                         (assoc :type type)

                                         (= type :edit-theme)
                                         (assoc :theme-path theme-path))))))
```

What do you think? I consider this to be more explicit, and to introduce less coupling between this component and the inner ones.

Code after:
        on-save
        (mf/use-fn
         (fn [theme]
           (st/emit! (ptk/event ::ev/event {::ev/name "create-tokens-theme"})
                     (wdt/create-token-theme theme))))
        has-prev-view (has-prev-view (:prev-type state))]

    [:> edit-create-theme*
     {:change-view change-view
      :theme theme
      :on-save on-save
      :has-prev-view has-prev-view}]))

(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}))
        state       (deref state*)

        change-view (mf/use-fn
                     (fn [type & {:keys [theme-path]}]
                       (swap! state* (fn [current-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
                    :themes-overview (if (empty? themes) empty-themes themes-overview)
                    :edit-theme edit-theme
                    :create-theme create-theme)]
    [:& component {:state state
                   :change-view change-view}]))

(mf/defc token-themes-modal
  {::mf/wrap-props false
   ::mf/register modal/components
   ::mf/register-as :tokens/themes}
  []
  [:div {:class (stl/css :modal-overlay)}
   [:div {:class (stl/css :modal-dialog)
          :data-testid "token-theme-update-create-modal"}
    [:> icon-button* {:class (stl/css :close-btn)
                      :on-click modal/hide!
                      :aria-label (tr "labels.close")
                      :variant "action"
                      :icon "close"}]