diff --git a/frontend/src/app/main/ui/workspace.cljs b/frontend/src/app/main/ui/workspace.cljs index 3c32733314..a7a905a397 100644 --- a/frontend/src/app/main/ui/workspace.cljs +++ b/frontend/src/app/main/ui/workspace.cljs @@ -36,7 +36,7 @@ [app.main.ui.workspace.tokens.export.modal] [app.main.ui.workspace.tokens.import] [app.main.ui.workspace.tokens.import.modal] - [app.main.ui.workspace.tokens.modals] + [app.main.ui.workspace.tokens.management.create.modals] [app.main.ui.workspace.tokens.settings] [app.main.ui.workspace.tokens.themes.create-modal] [app.main.ui.workspace.viewport :refer [viewport*]] diff --git a/frontend/src/app/main/ui/workspace/tokens/management.cljs b/frontend/src/app/main/ui/workspace/tokens/management.cljs new file mode 100644 index 0000000000..6428a3ff07 --- /dev/null +++ b/frontend/src/app/main/ui/workspace/tokens/management.cljs @@ -0,0 +1,155 @@ +(ns app.main.ui.workspace.tokens.management + (:require-macros [app.main.style :as stl]) + (:require + [app.common.data :as d] + [app.common.types.tokens-lib :as ctob] + [app.config :as cf] + [app.main.data.style-dictionary :as sd] + [app.main.data.workspace.tokens.application :as dwta] + [app.main.data.workspace.tokens.library-edit :as dwtl] + [app.main.refs :as refs] + [app.main.store :as st] + [app.main.ui.ds.foundations.assets.icon :as i] + [app.main.ui.ds.foundations.typography.text :refer [text*]] + [app.main.ui.workspace.tokens.management.context-menu :refer [token-context-menu]] + [app.main.ui.workspace.tokens.management.group :refer [token-group*]] + [app.util.array :as array] + [app.util.i18n :refer [tr]] + [okulary.core :as l] + [rumext.v2 :as mf])) + +(def ref:token-type-open-status + (l/derived (l/key :open-status-by-type) refs/workspace-tokens)) + +(defn- get-sorted-token-groups + "Separate token-types into groups of `empty` or `filled` depending if + tokens exist for that type. Sort each group alphabetically (by their type). + If `:token-units` is not in cf/flags, number tokens are excluded." + [tokens-by-type] + (let [token-units? (contains? cf/flags :token-units) + token-typography-types? (contains? cf/flags :token-typography-types) + all-types (cond-> dwta/token-properties + (not token-units?) (dissoc :number) + (not token-typography-types?) (dissoc :font-size)) + all-types (-> all-types keys seq)] + (loop [empty #js [] + filled #js [] + types all-types] + (if-let [type (first types)] + (if (not-empty (get tokens-by-type type)) + (recur empty + (array/conj! filled type) + (rest types)) + (recur (array/conj! empty type) + filled + (rest types))) + [(seq (array/sort! empty)) + (seq (array/sort! filled))])))) + +(mf/defc tokens-section* + {::mf/private true} + [{:keys [tokens-lib]}] + (let [objects (mf/deref refs/workspace-page-objects) + selected (mf/deref refs/selected-shapes) + open-status (mf/deref ref:token-type-open-status) + + selected-shapes + (mf/with-memo [selected objects] + (into [] (keep (d/getf objects)) selected)) + + active-theme-tokens + (mf/with-memo [tokens-lib] + (if tokens-lib + (ctob/get-tokens-in-active-sets tokens-lib) + {})) + + ;; Resolve tokens as second step + active-theme-tokens' + (sd/use-resolved-tokens* active-theme-tokens) + + ;; This only checks for the currently explicitly selected set + ;; name, it is ephimeral and can be nil + selected-token-set-name + (mf/deref refs/selected-token-set-name) + + selected-token-set + (when selected-token-set-name + (some-> tokens-lib (ctob/get-set selected-token-set-name))) + + ;; If we have not selected any set explicitly we just + ;; select the first one from the list of sets + selected-token-set-tokens + (when selected-token-set + (get selected-token-set :tokens)) + + tokens + (mf/with-memo [active-theme-tokens selected-token-set-tokens] + (merge active-theme-tokens selected-token-set-tokens)) + + tokens + (sd/use-resolved-tokens* tokens) + + tokens-by-type + (mf/with-memo [tokens selected-token-set-tokens] + (let [tokens (reduce-kv (fn [tokens k _] + (if (contains? selected-token-set-tokens k) + tokens + (dissoc tokens k))) + tokens + tokens)] + (ctob/group-by-type tokens))) + + active-token-sets-names + (mf/with-memo [tokens-lib] + (some-> tokens-lib (ctob/get-active-themes-set-names))) + + token-set-active? + (mf/use-fn + (mf/deps active-token-sets-names) + (fn [name] + (contains? active-token-sets-names name))) + + [empty-group filled-group] + (mf/with-memo [tokens-by-type] + (get-sorted-token-groups tokens-by-type))] + + (mf/with-effect [tokens-lib selected-token-set-name] + (when (and tokens-lib + (or (nil? selected-token-set-name) + (and selected-token-set-name + (not (ctob/get-set tokens-lib selected-token-set-name))))) + (let [match (->> (ctob/get-sets tokens-lib) + (first) + (:name))] + (st/emit! (dwtl/set-selected-token-set-name match))))) + + [:* + [:& token-context-menu] + [:div {:class (stl/css :sets-header-container)} + [:> text* {:as "span" :typography "headline-small" :class (stl/css :sets-header)} (tr "workspace.tokens.tokens-section-title" selected-token-set-name)] + [:div {:class (stl/css :sets-header-status) :title (tr "workspace.tokens.inactive-set-description")} + ;; NOTE: when no set in tokens-lib, the selected-token-set-name + ;; will be `nil`, so for properly hide the inactive message we + ;; check that at least `selected-token-set-name` has a value + (when (and (some? selected-token-set-name) + (not (token-set-active? selected-token-set-name))) + [:* + [:> i/icon* {:class (stl/css :sets-header-status-icon) :icon-id i/eye-off}] + [:> text* {:as "span" :typography "body-small" :class (stl/css :sets-header-status-text)} + (tr "workspace.tokens.inactive-set")]])]] + + (for [type filled-group] + (let [tokens (get tokens-by-type type)] + [:> token-group* {:key (name type) + :is-open (get open-status type false) + :type type + :selected-shapes selected-shapes + :active-theme-tokens active-theme-tokens' + :tokens tokens}])) + + (for [type empty-group] + [:> token-group* {:key (name type) + :type type + :selected-shapes selected-shapes + :active-theme-tokens active-theme-tokens' + :tokens []}])])) diff --git a/frontend/src/app/main/ui/workspace/tokens/management.scss b/frontend/src/app/main/ui/workspace/tokens/management.scss new file mode 100644 index 0000000000..57e274fb37 --- /dev/null +++ b/frontend/src/app/main/ui/workspace/tokens/management.scss @@ -0,0 +1,36 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. +// +// Copyright (c) KALEIDOS INC + +@use "../../ds/typography.scss" as *; + +.sets-header-container { + @include use-typography("headline-small"); + padding: var(--sp-s); + color: var(--title-foreground-color); + word-break: break-word; + display: flex; + align-items: flex-start; + justify-content: space-between; + gap: var(--sp-xs); + margin-block-start: var(--sp-s); +} + +.sets-header { + flex: 1; +} + +.sets-header-status { + @include use-typography("body-small"); + text-transform: none; + color: var(--color-foreground-secondary); + display: flex; + align-items: center; + gap: var(--sp-xs); +} + +.sets-header-status-text { + font-style: italic; +} diff --git a/frontend/src/app/main/ui/workspace/tokens/common/context_menu.cljs b/frontend/src/app/main/ui/workspace/tokens/management/context_menu.cljs similarity index 99% rename from frontend/src/app/main/ui/workspace/tokens/common/context_menu.cljs rename to frontend/src/app/main/ui/workspace/tokens/management/context_menu.cljs index 4bab592e47..8496a254f2 100644 --- a/frontend/src/app/main/ui/workspace/tokens/common/context_menu.cljs +++ b/frontend/src/app/main/ui/workspace/tokens/management/context_menu.cljs @@ -4,7 +4,7 @@ ;; ;; Copyright (c) KALEIDOS INC -(ns app.main.ui.workspace.tokens.common.context-menu +(ns app.main.ui.workspace.tokens.management.context-menu (:require-macros [app.main.style :as stl]) (:require [app.common.data :as d] diff --git a/frontend/src/app/main/ui/workspace/tokens/common/context_menu.scss b/frontend/src/app/main/ui/workspace/tokens/management/context_menu.scss similarity index 100% rename from frontend/src/app/main/ui/workspace/tokens/common/context_menu.scss rename to frontend/src/app/main/ui/workspace/tokens/management/context_menu.scss diff --git a/frontend/src/app/main/ui/workspace/tokens/form.cljs b/frontend/src/app/main/ui/workspace/tokens/management/create/form.cljs similarity index 99% rename from frontend/src/app/main/ui/workspace/tokens/form.cljs rename to frontend/src/app/main/ui/workspace/tokens/management/create/form.cljs index 58202b2ba6..0e627ecf0f 100644 --- a/frontend/src/app/main/ui/workspace/tokens/form.cljs +++ b/frontend/src/app/main/ui/workspace/tokens/management/create/form.cljs @@ -4,7 +4,7 @@ ;; ;; Copyright (c) KALEIDOS INC -(ns app.main.ui.workspace.tokens.form +(ns app.main.ui.workspace.tokens.management.create.form (:require-macros [app.main.style :as stl]) (:require [app.common.colors :as c] @@ -31,7 +31,7 @@ [app.main.ui.ds.notifications.context-notification :refer [context-notification*]] [app.main.ui.workspace.colorpicker :as colorpicker] [app.main.ui.workspace.colorpicker.ramp :refer [ramp-selector*]] - [app.main.ui.workspace.tokens.components.controls.input-tokens-value :refer [input-tokens-value*]] + [app.main.ui.workspace.tokens.management.create.input-tokens-value :refer [input-tokens-value*]] [app.util.dom :as dom] [app.util.functions :as uf] [app.util.i18n :refer [tr]] diff --git a/frontend/src/app/main/ui/workspace/tokens/form.scss b/frontend/src/app/main/ui/workspace/tokens/management/create/form.scss similarity index 100% rename from frontend/src/app/main/ui/workspace/tokens/form.scss rename to frontend/src/app/main/ui/workspace/tokens/management/create/form.scss diff --git a/frontend/src/app/main/ui/workspace/tokens/components/controls/input_token_color_bullet.cljs b/frontend/src/app/main/ui/workspace/tokens/management/create/input_token_color_bullet.cljs similarity index 92% rename from frontend/src/app/main/ui/workspace/tokens/components/controls/input_token_color_bullet.cljs rename to frontend/src/app/main/ui/workspace/tokens/management/create/input_token_color_bullet.cljs index 715f7699c5..18ed631f9c 100644 --- a/frontend/src/app/main/ui/workspace/tokens/components/controls/input_token_color_bullet.cljs +++ b/frontend/src/app/main/ui/workspace/tokens/management/create/input_token_color_bullet.cljs @@ -4,7 +4,7 @@ ;; ;; Copyright (c) KALEIDOS INC -(ns app.main.ui.workspace.tokens.components.controls.input-token-color-bullet +(ns app.main.ui.workspace.tokens.management.create.input-token-color-bullet (:require-macros [app.main.style :as stl]) (:require [app.main.data.workspace.tokens.color :as dwtc] diff --git a/frontend/src/app/main/ui/workspace/tokens/components/controls/input_token_color_bullet.scss b/frontend/src/app/main/ui/workspace/tokens/management/create/input_token_color_bullet.scss similarity index 100% rename from frontend/src/app/main/ui/workspace/tokens/components/controls/input_token_color_bullet.scss rename to frontend/src/app/main/ui/workspace/tokens/management/create/input_token_color_bullet.scss diff --git a/frontend/src/app/main/ui/workspace/tokens/components/controls/input_tokens_value.cljs b/frontend/src/app/main/ui/workspace/tokens/management/create/input_tokens_value.cljs similarity index 92% rename from frontend/src/app/main/ui/workspace/tokens/components/controls/input_tokens_value.cljs rename to frontend/src/app/main/ui/workspace/tokens/management/create/input_tokens_value.cljs index 1be7646f10..0abeb85863 100644 --- a/frontend/src/app/main/ui/workspace/tokens/components/controls/input_tokens_value.cljs +++ b/frontend/src/app/main/ui/workspace/tokens/management/create/input_tokens_value.cljs @@ -4,14 +4,14 @@ ;; ;; Copyright (c) KALEIDOS INC -(ns app.main.ui.workspace.tokens.components.controls.input-tokens-value +(ns app.main.ui.workspace.tokens.management.create.input-tokens-value (:require-macros [app.main.style :as stl]) (:require [app.common.data :as d] [app.common.data.macros :as dm] [app.main.ui.ds.controls.utilities.input-field :refer [input-field*]] [app.main.ui.ds.controls.utilities.label :refer [label*]] - [app.main.ui.workspace.tokens.components.controls.input-token-color-bullet :refer [input-token-color-bullet*]] + [app.main.ui.workspace.tokens.management.create.input-token-color-bullet :refer [input-token-color-bullet*]] [rumext.v2 :as mf])) (def ^:private schema::input-tokens-value diff --git a/frontend/src/app/main/ui/workspace/tokens/components/controls/input_tokens_value.scss b/frontend/src/app/main/ui/workspace/tokens/management/create/input_tokens_value.scss similarity index 100% rename from frontend/src/app/main/ui/workspace/tokens/components/controls/input_tokens_value.scss rename to frontend/src/app/main/ui/workspace/tokens/management/create/input_tokens_value.scss diff --git a/frontend/src/app/main/ui/workspace/tokens/modals.cljs b/frontend/src/app/main/ui/workspace/tokens/management/create/modals.cljs similarity index 97% rename from frontend/src/app/main/ui/workspace/tokens/modals.cljs rename to frontend/src/app/main/ui/workspace/tokens/management/create/modals.cljs index 9f7f8594d8..25eade8097 100644 --- a/frontend/src/app/main/ui/workspace/tokens/modals.cljs +++ b/frontend/src/app/main/ui/workspace/tokens/management/create/modals.cljs @@ -4,7 +4,7 @@ ;; ;; Copyright (c) KALEIDOS INC -(ns app.main.ui.workspace.tokens.modals +(ns app.main.ui.workspace.tokens.management.create.modals (:require-macros [app.main.style :as stl]) (:require [app.common.data.macros :as dm] @@ -12,7 +12,7 @@ [app.main.refs :as refs] [app.main.ui.ds.buttons.icon-button :refer [icon-button*]] [app.main.ui.ds.foundations.assets.icon :as i] - [app.main.ui.workspace.tokens.form :refer [form]] + [app.main.ui.workspace.tokens.management.create.form :refer [form]] [app.util.i18n :refer [tr]] [okulary.core :as l] [rumext.v2 :as mf])) @@ -22,7 +22,7 @@ (defn calculate-position "Calculates the style properties for the given coordinates and position" [{vh :height} position x y color?] - (let [;; picker height in pixels + (let [;; picker height in pixels ;; TODO: Revisit these harcoded values h (if color? 610 510) ;; Checks for overflow outside the viewport height diff --git a/frontend/src/app/main/ui/workspace/tokens/modals.scss b/frontend/src/app/main/ui/workspace/tokens/management/create/modals.scss similarity index 100% rename from frontend/src/app/main/ui/workspace/tokens/modals.scss rename to frontend/src/app/main/ui/workspace/tokens/management/create/modals.scss diff --git a/frontend/src/app/main/ui/workspace/tokens/management/group.cljs b/frontend/src/app/main/ui/workspace/tokens/management/group.cljs new file mode 100644 index 0000000000..b78411c5e9 --- /dev/null +++ b/frontend/src/app/main/ui/workspace/tokens/management/group.cljs @@ -0,0 +1,119 @@ +;; This Source Code Form is subject to the terms of the Mozilla Public +;; License, v. 2.0. If a copy of the MPL was not distributed with this +;; file, You can obtain one at http://mozilla.org/MPL/2.0/. +;; +;; Copyright (c) KALEIDOS INC + + +(ns app.main.ui.workspace.tokens.management.group + (:require-macros [app.main.style :as stl]) + (:require + [app.main.data.modal :as modal] + [app.main.data.workspace.tokens.application :as dwta] + [app.main.data.workspace.tokens.library-edit :as dwtl] + [app.main.refs :as refs] + [app.main.store :as st] + [app.main.ui.context :as ctx] + [app.main.ui.ds.buttons.icon-button :refer [icon-button*]] + [app.main.ui.workspace.sidebar.assets.common :as cmm] + [app.main.ui.workspace.tokens.management.token-pill :refer [token-pill*]] + [app.util.dom :as dom] + [app.util.i18n :refer [tr]] + [rumext.v2 :as mf])) + +(defn token-section-icon + [type] + (case type + :border-radius "corner-radius" + :color "drop" + :boolean "boolean-difference" + :font-size "text-font-size" + :opacity "percentage" + :number "number" + :rotation "rotation" + :spacing "padding-extended" + :string "text-mixed" + :stroke-width "stroke-size" + :typography "text" + :dimensions "expand" + :sizing "expand" + "add")) + +(mf/defc token-group* + {::mf/private true} + [{:keys [type tokens selected-shapes active-theme-tokens is-open]}] + (let [{:keys [modal title]} + (get dwta/token-properties type) + editing-ref (mf/deref refs/workspace-editor-state) + not-editing? (empty? editing-ref) + + can-edit? + (mf/use-ctx ctx/can-edit?) + + tokens + (mf/with-memo [tokens] + (vec (sort-by :name tokens))) + + on-context-menu + (mf/use-fn + (fn [event token] + (dom/prevent-default event) + (st/emit! (dwtl/assign-token-context-menu + {:type :token + :position (dom/get-client-position event) + :errors (:errors token) + :token-name (:name token)})))) + + on-toggle-open-click + (mf/use-fn + (mf/deps is-open type) + #(st/emit! (dwtl/set-token-type-section-open type (not is-open)))) + + on-popover-open-click + (mf/use-fn + (mf/deps type title modal) + (fn [event] + (dom/stop-propagation event) + (st/emit! (dwtl/set-token-type-section-open type true) + ;; FIXME: use dom/get-client-position + (modal/show (:key modal) + {:x (.-clientX ^js event) + :y (.-clientY ^js event) + :position :right + :fields (:fields modal) + :title title + :action "create" + :token-type type})))) + + on-token-pill-click + (mf/use-fn + (mf/deps selected-shapes not-editing?) + (fn [event token] + (dom/stop-propagation event) + (when (and not-editing? (seq selected-shapes)) + (st/emit! (dwta/toggle-token {:token token + :shapes selected-shapes})))))] + + [:div {:on-click on-toggle-open-click :class (stl/css :token-section-wrapper)} + [:& cmm/asset-section {:icon (token-section-icon type) + :title title + :section :tokens + :assets-count (count tokens) + :open? is-open} + [:& cmm/asset-section-block {:role :title-button} + (when can-edit? + [:> icon-button* {:on-click on-popover-open-click + :variant "ghost" + :icon "add" + :aria-label (tr "workspace.tokens.add-token" title)}])] + (when is-open + [:& cmm/asset-section-block {:role :content} + [:div {:class (stl/css :token-pills-wrapper)} + (for [token tokens] + [:> token-pill* + {:key (:name token) + :token token + :selected-shapes selected-shapes + :active-theme-tokens active-theme-tokens + :on-click on-token-pill-click + :on-context-menu on-context-menu}])]])]])) diff --git a/frontend/src/app/main/ui/workspace/tokens/management/group.scss b/frontend/src/app/main/ui/workspace/tokens/management/group.scss new file mode 100644 index 0000000000..e46bfb846f --- /dev/null +++ b/frontend/src/app/main/ui/workspace/tokens/management/group.scss @@ -0,0 +1,11 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. +// +// Copyright (c) KALEIDOS INC + +.token-pills-wrapper { + display: flex; + gap: var(--sp-xs); + flex-wrap: wrap; +} diff --git a/frontend/src/app/main/ui/workspace/tokens/token_pill.cljs b/frontend/src/app/main/ui/workspace/tokens/management/token_pill.cljs similarity index 99% rename from frontend/src/app/main/ui/workspace/tokens/token_pill.cljs rename to frontend/src/app/main/ui/workspace/tokens/management/token_pill.cljs index fe532abacd..085597795e 100644 --- a/frontend/src/app/main/ui/workspace/tokens/token_pill.cljs +++ b/frontend/src/app/main/ui/workspace/tokens/management/token_pill.cljs @@ -4,7 +4,7 @@ ;; ;; Copyright (c) KALEIDOS INC -(ns app.main.ui.workspace.tokens.token-pill +(ns app.main.ui.workspace.tokens.management.token-pill (:require-macros [app.common.data.macros :as dm] [app.main.style :as stl]) diff --git a/frontend/src/app/main/ui/workspace/tokens/token_pill.scss b/frontend/src/app/main/ui/workspace/tokens/management/token_pill.scss similarity index 98% rename from frontend/src/app/main/ui/workspace/tokens/token_pill.scss rename to frontend/src/app/main/ui/workspace/tokens/management/token_pill.scss index aa6d865deb..6379e77f81 100644 --- a/frontend/src/app/main/ui/workspace/tokens/token_pill.scss +++ b/frontend/src/app/main/ui/workspace/tokens/management/token_pill.scss @@ -4,8 +4,8 @@ // // Copyright (c) KALEIDOS INC -@use "../../ds/typography.scss" as *; -@use "../../ds/borders.scss" as *; +@use "../../../ds/typography.scss" as *; +@use "../../../ds/borders.scss" as *; @import "refactor/common-refactor.scss"; .token-pill { diff --git a/frontend/src/app/main/ui/workspace/tokens/sidebar.cljs b/frontend/src/app/main/ui/workspace/tokens/sidebar.cljs index a9aaa8885d..a83c936870 100644 --- a/frontend/src/app/main/ui/workspace/tokens/sidebar.cljs +++ b/frontend/src/app/main/ui/workspace/tokens/sidebar.cljs @@ -7,166 +7,30 @@ (ns app.main.ui.workspace.tokens.sidebar (:require-macros [app.main.style :as stl]) (:require - [app.common.data :as d] [app.common.types.tokens-lib :as ctob] [app.config :as cf] [app.main.data.modal :as modal] - [app.main.data.style-dictionary :as sd] - [app.main.data.workspace.tokens.application :as dwta] - [app.main.data.workspace.tokens.library-edit :as dwtl] [app.main.refs :as refs] - [app.main.store :as st] [app.main.ui.components.dropdown-menu :refer [dropdown-menu dropdown-menu-item*]] [app.main.ui.components.title-bar :refer [title-bar]] [app.main.ui.context :as ctx] [app.main.ui.ds.buttons.button :refer [button*]] [app.main.ui.ds.buttons.icon-button :refer [icon-button*]] - [app.main.ui.ds.foundations.assets.icon :as i] - [app.main.ui.ds.foundations.typography.text :refer [text*]] [app.main.ui.hooks :as h] [app.main.ui.hooks.resize :refer [use-resize-hook]] - [app.main.ui.workspace.sidebar.assets.common :as cmm] - [app.main.ui.workspace.tokens.common.context-menu :refer [token-context-menu]] + [app.main.ui.workspace.tokens.management :refer [tokens-section*]] [app.main.ui.workspace.tokens.sets :as tsets] [app.main.ui.workspace.tokens.sets.context-menu :refer [token-set-context-menu*]] [app.main.ui.workspace.tokens.sets.lists :as tsetslist] [app.main.ui.workspace.tokens.themes :refer [themes-header*]] - [app.main.ui.workspace.tokens.token-pill :refer [token-pill*]] - [app.util.array :as array] [app.util.dom :as dom] [app.util.i18n :refer [tr]] - [okulary.core :as l] [rumext.v2 :as mf] [shadow.resource])) -(def ref:token-type-open-status - (l/derived (l/key :open-status-by-type) refs/workspace-tokens)) - ;; Components ------------------------------------------------------------------ -(defn token-section-icon - [type] - (case type - :border-radius "corner-radius" - :color "drop" - :boolean "boolean-difference" - :font-size "text-font-size" - :opacity "percentage" - :number "number" - :rotation "rotation" - :spacing "padding-extended" - :string "text-mixed" - :stroke-width "stroke-size" - :typography "text" - :dimensions "expand" - :sizing "expand" - "add")) - -(mf/defc token-group* - {::mf/private true} - [{:keys [type tokens selected-shapes active-theme-tokens is-open]}] - (let [{:keys [modal title]} - (get dwta/token-properties type) - editing-ref (mf/deref refs/workspace-editor-state) - not-editing? (empty? editing-ref) - - can-edit? - (mf/use-ctx ctx/can-edit?) - - tokens - (mf/with-memo [tokens] - (vec (sort-by :name tokens))) - - on-context-menu - (mf/use-fn - (fn [event token] - (dom/prevent-default event) - (st/emit! (dwtl/assign-token-context-menu - {:type :token - :position (dom/get-client-position event) - :errors (:errors token) - :token-name (:name token)})))) - - on-toggle-open-click - (mf/use-fn - (mf/deps is-open type) - #(st/emit! (dwtl/set-token-type-section-open type (not is-open)))) - - on-popover-open-click - (mf/use-fn - (mf/deps type title modal) - (fn [event] - (dom/stop-propagation event) - (st/emit! (dwtl/set-token-type-section-open type true) - ;; FIXME: use dom/get-client-position - (modal/show (:key modal) - {:x (.-clientX ^js event) - :y (.-clientY ^js event) - :position :right - :fields (:fields modal) - :title title - :action "create" - :token-type type})))) - - on-token-pill-click - (mf/use-fn - (mf/deps selected-shapes not-editing?) - (fn [event token] - (dom/stop-propagation event) - (when (and not-editing? (seq selected-shapes)) - (st/emit! (dwta/toggle-token {:token token - :shapes selected-shapes})))))] - - [:div {:on-click on-toggle-open-click :class (stl/css :token-section-wrapper)} - [:& cmm/asset-section {:icon (token-section-icon type) - :title title - :section :tokens - :assets-count (count tokens) - :open? is-open} - [:& cmm/asset-section-block {:role :title-button} - (when can-edit? - [:> icon-button* {:on-click on-popover-open-click - :variant "ghost" - :icon "add" - :aria-label (tr "workspace.tokens.add-token" title)}])] - (when is-open - [:& cmm/asset-section-block {:role :content} - [:div {:class (stl/css :token-pills-wrapper)} - (for [token tokens] - [:> token-pill* - {:key (:name token) - :token token - :selected-shapes selected-shapes - :active-theme-tokens active-theme-tokens - :on-click on-token-pill-click - :on-context-menu on-context-menu}])]])]])) - -(defn- get-sorted-token-groups - "Separate token-types into groups of `empty` or `filled` depending if - tokens exist for that type. Sort each group alphabetically (by their type). - If `:token-units` is not in cf/flags, number tokens are excluded." - [tokens-by-type] - (let [token-units? (contains? cf/flags :token-units) - token-typography-types? (contains? cf/flags :token-typography-types) - all-types (cond-> dwta/token-properties - (not token-units?) (dissoc :number) - (not token-typography-types?) (dissoc :font-size)) - all-types (-> all-types keys seq)] - (loop [empty #js [] - filled #js [] - types all-types] - (if-let [type (first types)] - (if (not-empty (get tokens-by-type type)) - (recur empty - (array/conj! filled type) - (rest types)) - (recur (array/conj! empty type) - filled - (rest types))) - [(seq (array/sort! empty)) - (seq (array/sort! filled))])))) - (mf/defc token-sets-list* {::mf/private true} [{:keys [tokens-lib]}] @@ -218,113 +82,6 @@ [:> token-sets-list* props]]])) -(mf/defc tokens-section* - [{:keys [tokens-lib]}] - (let [objects (mf/deref refs/workspace-page-objects) - selected (mf/deref refs/selected-shapes) - open-status (mf/deref ref:token-type-open-status) - - selected-shapes - (mf/with-memo [selected objects] - (into [] (keep (d/getf objects)) selected)) - - active-theme-tokens - (mf/with-memo [tokens-lib] - (if tokens-lib - (ctob/get-tokens-in-active-sets tokens-lib) - {})) - - ;; Resolve tokens as second step - active-theme-tokens' - (sd/use-resolved-tokens* active-theme-tokens) - - ;; This only checks for the currently explicitly selected set - ;; name, it is ephimeral and can be nil - selected-token-set-name - (mf/deref refs/selected-token-set-name) - - selected-token-set - (when selected-token-set-name - (some-> tokens-lib (ctob/get-set selected-token-set-name))) - - ;; If we have not selected any set explicitly we just - ;; select the first one from the list of sets - selected-token-set-tokens - (when selected-token-set - (get selected-token-set :tokens)) - - tokens - (mf/with-memo [active-theme-tokens selected-token-set-tokens] - (merge active-theme-tokens selected-token-set-tokens)) - - tokens - (sd/use-resolved-tokens* tokens) - - tokens-by-type - (mf/with-memo [tokens selected-token-set-tokens] - (let [tokens (reduce-kv (fn [tokens k _] - (if (contains? selected-token-set-tokens k) - tokens - (dissoc tokens k))) - tokens - tokens)] - (ctob/group-by-type tokens))) - - active-token-sets-names - (mf/with-memo [tokens-lib] - (some-> tokens-lib (ctob/get-active-themes-set-names))) - - token-set-active? - (mf/use-fn - (mf/deps active-token-sets-names) - (fn [name] - (contains? active-token-sets-names name))) - - [empty-group filled-group] - (mf/with-memo [tokens-by-type] - (get-sorted-token-groups tokens-by-type))] - - (mf/with-effect [tokens-lib selected-token-set-name] - (when (and tokens-lib - (or (nil? selected-token-set-name) - (and selected-token-set-name - (not (ctob/get-set tokens-lib selected-token-set-name))))) - (let [match (->> (ctob/get-sets tokens-lib) - (first) - (:name))] - (st/emit! (dwtl/set-selected-token-set-name match))))) - - [:* - [:& token-context-menu] - [:div {:class (stl/css :sets-header-container)} - [:> text* {:as "span" :typography "headline-small" :class (stl/css :sets-header)} (tr "workspace.tokens.tokens-section-title" selected-token-set-name)] - [:div {:class (stl/css :sets-header-status) :title (tr "workspace.tokens.inactive-set-description")} - ;; NOTE: when no set in tokens-lib, the selected-token-set-name - ;; will be `nil`, so for properly hide the inactive message we - ;; check that at least `selected-token-set-name` has a value - (when (and (some? selected-token-set-name) - (not (token-set-active? selected-token-set-name))) - [:* - [:> i/icon* {:class (stl/css :sets-header-status-icon) :icon-id i/eye-off}] - [:> text* {:as "span" :typography "body-small" :class (stl/css :sets-header-status-text)} - (tr "workspace.tokens.inactive-set")]])]] - - (for [type filled-group] - (let [tokens (get tokens-by-type type)] - [:> token-group* {:key (name type) - :is-open (get open-status type false) - :type type - :selected-shapes selected-shapes - :active-theme-tokens active-theme-tokens' - :tokens tokens}])) - - (for [type empty-group] - [:> token-group* {:key (name type) - :type type - :selected-shapes selected-shapes - :active-theme-tokens active-theme-tokens' - :tokens []}])])) - (mf/defc import-export-button* [] (let [show-menu* (mf/use-state false) diff --git a/frontend/src/app/main/ui/workspace/tokens/sidebar.scss b/frontend/src/app/main/ui/workspace/tokens/sidebar.scss index a234852628..bd6bacfe1f 100644 --- a/frontend/src/app/main/ui/workspace/tokens/sidebar.scss +++ b/frontend/src/app/main/ui/workspace/tokens/sidebar.scss @@ -36,38 +36,6 @@ scrollbar-gutter: stable; } -.sets-header-container { - @include use-typography("headline-small"); - padding: var(--sp-s); - color: var(--title-foreground-color); - word-break: break-word; -} - -.sets-header-container { - display: flex; - align-items: flex-start; - justify-content: space-between; - gap: var(--sp-xs); - margin-block-start: var(--sp-s); -} - -.sets-header { - flex: 1; -} - -.sets-header-status { - @include use-typography("body-small"); - text-transform: none; - color: var(--color-foreground-secondary); - display: flex; - align-items: center; - gap: var(--sp-xs); -} - -.sets-header-status-text { - font-style: italic; -} - .sidebar-header { display: flex; align-items: center; @@ -77,12 +45,6 @@ color: var(--layer-row-foreground-color); } -.token-pills-wrapper { - display: flex; - gap: var(--sp-xs); - flex-wrap: wrap; -} - .section-text-icon { font-size: $fs-12; width: var(--sp-l); diff --git a/frontend/test/frontend_tests/tokens/token_form_test.cljs b/frontend/test/frontend_tests/tokens/token_form_test.cljs index ea623bcbed..d42a325b0f 100644 --- a/frontend/test/frontend_tests/tokens/token_form_test.cljs +++ b/frontend/test/frontend_tests/tokens/token_form_test.cljs @@ -6,7 +6,7 @@ (ns frontend-tests.tokens.token-form-test (:require - [app.main.ui.workspace.tokens.form :as wtf] + [app.main.ui.workspace.tokens.management.create.form :as wtf] [cljs.test :as t :include-macros true] [malli.core :as m]))