mirror of
https://github.com/penpot/penpot.git
synced 2025-07-11 00:37:18 +02:00
♻️ Restructure UI files for token sets
This commit is contained in:
parent
e258030bc0
commit
ce59070fd1
10 changed files with 719 additions and 537 deletions
|
@ -99,7 +99,7 @@ export class WorkspacePage extends BaseWebSocketPage {
|
|||
this.tokenThemeUpdateCreateModal = page.getByTestId(
|
||||
"token-theme-update-create-modal",
|
||||
);
|
||||
this.tokenThemesSetsSidebar = page.getByTestId("token-themes-sets-sidebar");
|
||||
this.tokenThemesSetsSidebar = page.getByTestId("token-management-sidebar");
|
||||
this.tokensSidebar = page.getByTestId("tokens-sidebar");
|
||||
this.tokenSetItems = page.getByTestId("tokens-set-item");
|
||||
this.tokenSetGroupItems = page.getByTestId("tokens-set-group-item");
|
||||
|
|
|
@ -5,33 +5,18 @@
|
|||
;; Copyright (c) KALEIDOS INC
|
||||
|
||||
(ns app.main.ui.workspace.tokens.sets
|
||||
(:require-macros [app.main.style :as stl])
|
||||
(:require
|
||||
[app.common.data.macros :as dm]
|
||||
[app.common.types.tokens-lib :as ctob]
|
||||
[app.main.data.event :as ev]
|
||||
[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.ds.foundations.assets.icon :refer [icon*] :as ic]
|
||||
[app.main.ui.ds.foundations.typography.text :refer [text*]]
|
||||
[app.main.ui.hooks :as h]
|
||||
[app.util.dom :as dom]
|
||||
[app.util.i18n :refer [tr]]
|
||||
[app.util.keyboard :as kbd]
|
||||
[cuerdas.core :as str]
|
||||
[potok.v2.core :as ptk]
|
||||
[app.main.ui.workspace.tokens.sets.helpers :as sets-helpers]
|
||||
[app.main.ui.workspace.tokens.sets.lists :refer [controlled-sets-list*]]
|
||||
[rumext.v2 :as mf]))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; HELPERS
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(defn- on-start-creation
|
||||
[]
|
||||
(st/emit! (dwtl/start-token-set-creation [])))
|
||||
(defn- on-select-token-set-click [name]
|
||||
(st/emit! (dwtl/set-selected-token-set-name name)))
|
||||
|
||||
(defn- on-toggle-token-set-click [name]
|
||||
(st/emit! (dwtl/toggle-token-set name)))
|
||||
|
@ -39,498 +24,6 @@
|
|||
(defn- on-toggle-token-set-group-click [path]
|
||||
(st/emit! (dwtl/toggle-token-set-group path)))
|
||||
|
||||
(defn- on-select-token-set-click [name]
|
||||
(st/emit! (dwtl/set-selected-token-set-name name)))
|
||||
|
||||
(defn on-update-token-set
|
||||
[token-set name]
|
||||
(st/emit! (dwtl/clear-token-set-edition)
|
||||
(dwtl/update-token-set token-set name)))
|
||||
|
||||
(defn- on-update-token-set-group
|
||||
[path name]
|
||||
(st/emit! (dwtl/clear-token-set-edition)
|
||||
(dwtl/rename-token-set-group path name)))
|
||||
|
||||
(defn- on-create-token-set
|
||||
[parent-set name]
|
||||
(let [;; FIXME: this code should be reusable under helper under
|
||||
;; common types namespace
|
||||
name
|
||||
(if-let [parent-path (ctob/get-set-path parent-set)]
|
||||
(->> (concat parent-path (ctob/split-set-name name))
|
||||
(ctob/join-set-path))
|
||||
(ctob/normalize-set-name name))]
|
||||
|
||||
(st/emit! (ptk/data-event ::ev/event {::ev/name "create-token-set" :name name})
|
||||
(dwtl/create-token-set name))))
|
||||
|
||||
(defn group-edition-id
|
||||
"Prefix editing groups `edition-id` so it can be differentiated from sets with the same id."
|
||||
[edition-id]
|
||||
(str "group-" edition-id))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; COMPONENTS
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(mf/defc editing-label*
|
||||
{::mf/private true}
|
||||
[{:keys [default-value on-cancel on-submit]}]
|
||||
(let [on-submit
|
||||
(mf/use-fn
|
||||
(mf/deps on-cancel on-submit default-value)
|
||||
(fn [event]
|
||||
(let [value (dom/get-target-val event)]
|
||||
(if (or (str/empty? value)
|
||||
(= value default-value))
|
||||
(on-cancel)
|
||||
(on-submit value)))))
|
||||
|
||||
on-key-down
|
||||
(mf/use-fn
|
||||
(mf/deps on-submit on-cancel)
|
||||
(fn [event]
|
||||
(cond
|
||||
(kbd/enter? event) (on-submit event)
|
||||
(kbd/esc? event) (on-cancel))))]
|
||||
[:input
|
||||
{:class (stl/css :editing-node)
|
||||
:type "text"
|
||||
:on-blur on-submit
|
||||
:on-key-down on-key-down
|
||||
:maxlength "256"
|
||||
:auto-focus true
|
||||
:placeholder (tr "workspace.tokens.set-edit-placeholder")
|
||||
:default-value default-value}]))
|
||||
|
||||
(mf/defc checkbox*
|
||||
[{:keys [checked aria-label on-click disabled]}]
|
||||
(let [all? (true? checked)
|
||||
mixed? (= checked "mixed")
|
||||
checked? (or all? mixed?)]
|
||||
|
||||
[:div {:role "checkbox"
|
||||
:aria-checked (dm/str checked)
|
||||
:disabled disabled
|
||||
:title (when disabled (tr "workspace.tokens.no-permisions-set"))
|
||||
:tab-index 0
|
||||
:class (stl/css-case :checkbox-style true
|
||||
:checkbox-checked-style checked?
|
||||
:checkbox-disabled-checked (and checked? disabled)
|
||||
:checkbox-disabled disabled)
|
||||
:on-click (when-not disabled on-click)}
|
||||
|
||||
(when ^boolean checked?
|
||||
[:> icon*
|
||||
{:aria-label aria-label
|
||||
:class (stl/css :check-icon)
|
||||
:size "s"
|
||||
:icon-id (if mixed? ic/remove ic/tick)}])]))
|
||||
|
||||
(mf/defc inline-add-button*
|
||||
[]
|
||||
(let [can-edit? (mf/use-ctx ctx/can-edit?)]
|
||||
(if can-edit?
|
||||
[:div {:class (stl/css :empty-sets-wrapper)}
|
||||
[:> text* {:as "span" :typography "body-small" :class (stl/css :empty-state-message)}
|
||||
(tr "workspace.tokens.no-sets-yet")]
|
||||
[:button {:on-click on-start-creation
|
||||
:class (stl/css :create-set-button)}
|
||||
(tr "workspace.tokens.create-one")]]
|
||||
[:div {:class (stl/css :empty-sets-wrapper)}
|
||||
[:> text* {:as "span" :typography "body-small" :class (stl/css :empty-state-message)}
|
||||
(tr "workspace.tokens.no-sets-yet")]])))
|
||||
|
||||
(mf/defc add-button*
|
||||
[]
|
||||
[:> icon-button* {:variant "ghost"
|
||||
:icon "add"
|
||||
:on-click on-start-creation
|
||||
:aria-label (tr "workspace.tokens.add set")}])
|
||||
|
||||
(mf/defc sets-tree-set-group*
|
||||
{::mf/private true}
|
||||
[{:keys [id label tree-depth tree-path is-active is-selected is-draggable is-collapsed tree-index on-drop
|
||||
on-toggle-collapse on-toggle is-editing on-start-edition on-reset-edition on-edit-submit]}]
|
||||
|
||||
(let [can-edit?
|
||||
(mf/use-ctx ctx/can-edit?)
|
||||
|
||||
label-id
|
||||
(str id "-label")
|
||||
|
||||
on-context-menu
|
||||
(mf/use-fn
|
||||
(mf/deps is-editing id tree-path can-edit?)
|
||||
(fn [event]
|
||||
(dom/prevent-default event)
|
||||
(dom/stop-propagation event)
|
||||
(when (and can-edit? (not is-editing))
|
||||
(st/emit! (dwtl/assign-token-set-context-menu
|
||||
{:position (dom/get-client-position event)
|
||||
:is-group true
|
||||
:id id
|
||||
:edition-id (group-edition-id id)
|
||||
:path tree-path})))))
|
||||
|
||||
on-collapse-click
|
||||
(mf/use-fn
|
||||
(fn [event]
|
||||
(dom/prevent-default event)
|
||||
(dom/stop-propagation event)
|
||||
(on-toggle-collapse tree-path)))
|
||||
|
||||
on-double-click
|
||||
(mf/use-fn (mf/deps id) #(on-start-edition (group-edition-id id)))
|
||||
|
||||
on-checkbox-click
|
||||
(mf/use-fn
|
||||
(mf/deps on-toggle tree-path can-edit?)
|
||||
#(on-toggle tree-path))
|
||||
|
||||
on-edit-submit'
|
||||
(mf/use-fn
|
||||
(mf/deps tree-path on-edit-submit can-edit?)
|
||||
#(on-edit-submit tree-path %))
|
||||
|
||||
on-drop
|
||||
(mf/use-fn
|
||||
(mf/deps tree-index on-drop)
|
||||
(fn [position data]
|
||||
(on-drop tree-index position data)))
|
||||
|
||||
[dprops dref]
|
||||
(h/use-sortable
|
||||
:data-type "penpot/token-set"
|
||||
:on-drop on-drop
|
||||
:data {:index tree-index
|
||||
:is-group true}
|
||||
:detect-center? true
|
||||
:draggable? is-draggable)]
|
||||
|
||||
[:div {:ref dref
|
||||
:data-testid "tokens-set-group-item"
|
||||
:style {"--tree-depth" tree-depth}
|
||||
:class (stl/css-case :set-item-container true
|
||||
:set-item-group true
|
||||
:selected-set is-selected
|
||||
:dnd-over (= (:over dprops) :center)
|
||||
:dnd-over-top (= (:over dprops) :top)
|
||||
:dnd-over-bot (= (:over dprops) :bot))
|
||||
:on-context-menu on-context-menu}
|
||||
[:> icon-button*
|
||||
{:class (stl/css :set-item-group-collapse-button)
|
||||
:on-click on-collapse-click
|
||||
:data-testid "tokens-set-group-collapse"
|
||||
:aria-label (tr "labels.collapse")
|
||||
:icon (if is-collapsed "arrow-right" "arrow-down")
|
||||
:variant "action"}]
|
||||
(if is-editing
|
||||
[:> editing-label*
|
||||
{:default-value label
|
||||
:on-cancel on-reset-edition
|
||||
:on-submit on-edit-submit'}]
|
||||
[:*
|
||||
[:div {:class (stl/css :set-name)
|
||||
:role "button"
|
||||
:title label
|
||||
:tab-index 0
|
||||
:on-double-click on-double-click
|
||||
:id label-id}
|
||||
label]
|
||||
[:> checkbox*
|
||||
{:on-click on-checkbox-click
|
||||
:disabled (not can-edit?)
|
||||
:checked (case is-active
|
||||
:all true
|
||||
:partial "mixed"
|
||||
:none false)
|
||||
:arial-label (tr "workspace.tokens.select-set")}]])]))
|
||||
|
||||
(mf/defc sets-tree-set*
|
||||
[{:keys [id set label tree-depth tree-path tree-index is-selected is-active is-draggable is-editing
|
||||
on-select on-drop on-toggle on-start-edition on-reset-edition on-edit-submit]}]
|
||||
|
||||
(let [set-name (get set :name)
|
||||
can-edit? (mf/use-ctx ctx/can-edit?)
|
||||
|
||||
on-click
|
||||
(mf/use-fn
|
||||
(mf/deps is-editing tree-path)
|
||||
(fn [event]
|
||||
(dom/stop-propagation event)
|
||||
(when-not is-editing
|
||||
(when (fn? on-select)
|
||||
(on-select set-name)))))
|
||||
|
||||
on-context-menu
|
||||
(mf/use-fn
|
||||
(mf/deps is-editing id tree-path can-edit?)
|
||||
(fn [event]
|
||||
(dom/prevent-default event)
|
||||
(dom/stop-propagation event)
|
||||
(when (and can-edit? (not is-editing))
|
||||
(st/emit! (dwtl/assign-token-set-context-menu
|
||||
{:position (dom/get-client-position event)
|
||||
:is-group false
|
||||
:id id
|
||||
:edition-id id
|
||||
:path tree-path})))))
|
||||
|
||||
on-double-click
|
||||
(mf/use-fn (mf/deps id) #(on-start-edition id))
|
||||
|
||||
on-checkbox-click
|
||||
(mf/use-fn
|
||||
(mf/deps set-name on-toggle)
|
||||
(fn [event]
|
||||
(dom/stop-propagation event)
|
||||
(when (fn? on-toggle)
|
||||
(on-toggle set-name))))
|
||||
|
||||
on-edit-submit'
|
||||
(mf/use-fn
|
||||
(mf/deps set on-edit-submit)
|
||||
#(on-edit-submit set %))
|
||||
|
||||
on-drag
|
||||
(mf/use-fn
|
||||
(mf/deps tree-path)
|
||||
(fn [_]
|
||||
(when-not is-selected
|
||||
(on-select tree-path))))
|
||||
|
||||
on-drop
|
||||
(mf/use-fn
|
||||
(mf/deps tree-index on-drop)
|
||||
(fn [position data]
|
||||
(on-drop tree-index position data)))
|
||||
|
||||
[dprops dref]
|
||||
(h/use-sortable
|
||||
:data-type "penpot/token-set"
|
||||
:on-drag on-drag
|
||||
:on-drop on-drop
|
||||
:data {:index tree-index
|
||||
:is-group false}
|
||||
:draggable? is-draggable)
|
||||
|
||||
drop-over
|
||||
(get dprops :over)]
|
||||
|
||||
[:div {:ref dref
|
||||
:role "button"
|
||||
:data-testid "tokens-set-item"
|
||||
:style {"--tree-depth" tree-depth}
|
||||
:class (stl/css-case :set-item-container true
|
||||
:selected-set is-selected
|
||||
:dnd-over (= drop-over :center)
|
||||
:dnd-over-top (= drop-over :top)
|
||||
:dnd-over-bot (= drop-over :bot))
|
||||
:on-click on-click
|
||||
:on-double-click on-double-click
|
||||
:on-context-menu on-context-menu
|
||||
:aria-checked is-active}
|
||||
|
||||
[:> icon*
|
||||
{:icon-id "document"
|
||||
:class (stl/css-case :icon true
|
||||
:root-icon (not tree-depth))}]
|
||||
(if is-editing
|
||||
[:> editing-label*
|
||||
{:default-value label
|
||||
:on-cancel on-reset-edition
|
||||
:on-submit on-edit-submit'}]
|
||||
[:*
|
||||
[:div {:class (stl/css :set-name)}
|
||||
label]
|
||||
[:> checkbox*
|
||||
{:on-click on-checkbox-click
|
||||
:disabled (not can-edit?)
|
||||
:arial-label (tr "workspace.tokens.select-set")
|
||||
:checked is-active}]])]))
|
||||
|
||||
(mf/defc token-sets-tree*
|
||||
[{:keys [is-draggable
|
||||
selected
|
||||
is-token-set-group-active
|
||||
is-token-set-active
|
||||
on-start-edition
|
||||
on-reset-edition
|
||||
on-edit-submit-set
|
||||
on-edit-submit-group
|
||||
on-select
|
||||
on-toggle-set
|
||||
on-toggle-set-group
|
||||
token-sets
|
||||
new-path
|
||||
edition-id]}]
|
||||
|
||||
(let [collapsed-paths* (mf/use-state #{})
|
||||
collapsed-paths (deref collapsed-paths*)
|
||||
|
||||
collapsed?
|
||||
(mf/use-fn
|
||||
(mf/deps collapsed-paths)
|
||||
(partial contains? collapsed-paths))
|
||||
|
||||
on-drop
|
||||
(mf/use-fn
|
||||
(mf/deps collapsed-paths)
|
||||
(fn [tree-index position data]
|
||||
(let [params {:from-index (:index data)
|
||||
:to-index tree-index
|
||||
:position position
|
||||
:collapsed-paths collapsed-paths}]
|
||||
(if (:is-group data)
|
||||
(st/emit! (dwtl/drop-token-set-group params))
|
||||
(st/emit! (dwtl/drop-token-set params))))))
|
||||
|
||||
on-toggle-collapse
|
||||
(mf/use-fn
|
||||
(fn [path]
|
||||
(swap! collapsed-paths* #(if (contains? % path)
|
||||
(disj % path)
|
||||
(conj % path)))))]
|
||||
|
||||
(for [{:keys [id token-set index is-new is-group path parent-path depth] :as node}
|
||||
(ctob/sets-tree-seq token-sets
|
||||
{:skip-children-pred collapsed?
|
||||
:new-at-path new-path})]
|
||||
(cond
|
||||
^boolean is-group
|
||||
[:> sets-tree-set-group*
|
||||
{:key index
|
||||
:label (peek path)
|
||||
:id id
|
||||
:is-active (is-token-set-group-active path)
|
||||
:is-selected false
|
||||
:is-draggable is-draggable
|
||||
:is-editing (= edition-id (group-edition-id id))
|
||||
:is-collapsed (collapsed? path)
|
||||
:on-select on-select
|
||||
|
||||
:tree-path path
|
||||
:tree-depth depth
|
||||
:tree-index index
|
||||
:tree-parent-path parent-path
|
||||
|
||||
:on-drop on-drop
|
||||
:on-start-edition on-start-edition
|
||||
:on-reset-edition on-reset-edition
|
||||
:on-edit-submit on-edit-submit-group
|
||||
:on-toggle-collapse on-toggle-collapse
|
||||
:on-toggle on-toggle-set-group}]
|
||||
|
||||
^boolean is-new
|
||||
[:> sets-tree-set*
|
||||
{:key index
|
||||
:set token-set
|
||||
:label ""
|
||||
:id id
|
||||
:is-editing true
|
||||
:is-active true
|
||||
:is-selected true
|
||||
|
||||
:tree-path path
|
||||
:tree-depth depth
|
||||
:tree-index index
|
||||
:tree-parent-path parent-path
|
||||
|
||||
:on-drop on-drop
|
||||
:on-reset-edition on-reset-edition
|
||||
:on-edit-submit on-create-token-set}]
|
||||
|
||||
:else
|
||||
[:> sets-tree-set*
|
||||
{:key index
|
||||
:set token-set
|
||||
:id id
|
||||
:label (peek path)
|
||||
:is-editing (= edition-id id)
|
||||
:is-active (is-token-set-active id)
|
||||
:is-selected (= selected id)
|
||||
:is-draggable is-draggable
|
||||
:on-select on-select
|
||||
:tree-path path
|
||||
:tree-depth depth
|
||||
:tree-index index
|
||||
:tree-parent-path parent-path
|
||||
:on-toggle on-toggle-set
|
||||
:edition-id edition-id
|
||||
:on-start-edition on-start-edition
|
||||
:on-drop on-drop
|
||||
:on-reset-edition on-reset-edition
|
||||
:on-edit-submit on-edit-submit-set}]))))
|
||||
|
||||
(mf/defc controlled-sets-list*
|
||||
{::mf/props :obj}
|
||||
[{:keys [token-sets
|
||||
selected
|
||||
on-update-token-set
|
||||
on-update-token-set-group
|
||||
is-token-set-active
|
||||
is-token-set-group-active
|
||||
on-create-token-set
|
||||
on-toggle-token-set
|
||||
on-toggle-token-set-group
|
||||
on-start-edition
|
||||
on-reset-edition
|
||||
origin
|
||||
on-select
|
||||
new-path
|
||||
edition-id]}]
|
||||
|
||||
(assert (fn? is-token-set-group-active) "expected a function for `is-token-set-group-active` prop")
|
||||
(assert (fn? is-token-set-active) "expected a function for `is-token-set-active` prop")
|
||||
|
||||
(let [theme-modal? (= origin "theme-modal")
|
||||
can-edit? (mf/use-ctx ctx/can-edit?)
|
||||
draggable? (and (not theme-modal?) can-edit?)
|
||||
empty-state? (and theme-modal?
|
||||
(empty? token-sets)
|
||||
(not new-path))
|
||||
|
||||
;; NOTE: on-reset-edition and on-start-edition function can
|
||||
;; come as nil, in this case we need to provide a safe
|
||||
;; fallback for them
|
||||
on-reset-edition
|
||||
(mf/use-fn
|
||||
(mf/deps on-reset-edition)
|
||||
(fn [v]
|
||||
(when (fn? on-reset-edition)
|
||||
(on-reset-edition v))))
|
||||
|
||||
on-start-edition
|
||||
(mf/use-fn
|
||||
(mf/deps on-start-edition)
|
||||
(fn [v]
|
||||
(when (fn? on-start-edition)
|
||||
(on-start-edition v))))]
|
||||
|
||||
[:div {:class (stl/css :sets-list)}
|
||||
(if ^boolean empty-state?
|
||||
[:> text* {:as "span" :typography "body-small" :class (stl/css :empty-state-message-sets)}
|
||||
(tr "workspace.tokens.no-sets-create")]
|
||||
|
||||
[:> token-sets-tree*
|
||||
{:is-draggable draggable?
|
||||
:new-path new-path
|
||||
:edition-id edition-id
|
||||
:token-sets token-sets
|
||||
:selected selected
|
||||
:on-select on-select
|
||||
:is-token-set-active is-token-set-active
|
||||
:is-token-set-group-active is-token-set-group-active
|
||||
:on-toggle-set on-toggle-token-set
|
||||
:on-toggle-set-group on-toggle-token-set-group
|
||||
:on-create-token-set on-create-token-set
|
||||
:on-start-edition on-start-edition
|
||||
:on-reset-edition on-reset-edition
|
||||
:on-edit-submit-set on-update-token-set
|
||||
:on-edit-submit-group on-update-token-set-group}])]))
|
||||
|
||||
(mf/defc sets-list*
|
||||
[{:keys [tokens-lib selected new-path edition-id]}]
|
||||
|
||||
|
@ -589,6 +82,6 @@
|
|||
|
||||
:on-toggle-token-set on-toggle-token-set-click
|
||||
:on-toggle-token-set-group on-toggle-token-set-group-click
|
||||
:on-update-token-set on-update-token-set
|
||||
:on-update-token-set-group on-update-token-set-group
|
||||
:on-create-token-set on-create-token-set}]))
|
||||
:on-update-token-set sets-helpers/on-update-token-set
|
||||
:on-update-token-set-group sets-helpers/on-update-token-set-group
|
||||
:on-create-token-set sets-helpers/on-create-token-set}]))
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
;;
|
||||
;; Copyright (c) KALEIDOS INC
|
||||
|
||||
(ns app.main.ui.workspace.tokens.sets-context-menu
|
||||
(ns app.main.ui.workspace.tokens.sets.context-menu
|
||||
(:require-macros [app.main.style :as stl])
|
||||
(:require
|
||||
[app.common.data.macros :as dm]
|
|
@ -4,7 +4,7 @@
|
|||
//
|
||||
// Copyright (c) KALEIDOS INC
|
||||
|
||||
@use "../../ds/typography.scss" as t;
|
||||
@use "../../../ds/typography.scss" as t;
|
||||
@import "refactor/common-refactor.scss";
|
||||
|
||||
.token-set-context-menu {
|
36
frontend/src/app/main/ui/workspace/tokens/sets/helpers.cljs
Normal file
36
frontend/src/app/main/ui/workspace/tokens/sets/helpers.cljs
Normal file
|
@ -0,0 +1,36 @@
|
|||
(ns app.main.ui.workspace.tokens.sets.helpers
|
||||
(:require
|
||||
[app.common.types.tokens-lib :as ctob]
|
||||
[app.main.data.event :as ev]
|
||||
[app.main.data.workspace.tokens.library-edit :as dwtl]
|
||||
[app.main.store :as st]
|
||||
[potok.v2.core :as ptk]))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; HELPERS - Shared functions for token sets management
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(defn on-update-token-set
|
||||
[token-set name]
|
||||
(st/emit! (dwtl/clear-token-set-edition)
|
||||
(dwtl/update-token-set token-set name)))
|
||||
|
||||
(defn on-update-token-set-group
|
||||
[path name]
|
||||
(st/emit! (dwtl/clear-token-set-edition)
|
||||
(dwtl/rename-token-set-group path name)))
|
||||
|
||||
(defn on-create-token-set
|
||||
[parent-set name]
|
||||
(let [;; FIXME: this code should be reusable under helper under
|
||||
;; common types namespace
|
||||
name
|
||||
(if-let [parent-path (ctob/get-set-path parent-set)]
|
||||
(->> (concat parent-path (ctob/split-set-name name))
|
||||
(ctob/join-set-path))
|
||||
(ctob/normalize-set-name name))]
|
||||
|
||||
(st/emit! (ptk/data-event ::ev/event {::ev/name "create-token-set" :name name})
|
||||
(dwtl/create-token-set name))))
|
||||
|
||||
|
492
frontend/src/app/main/ui/workspace/tokens/sets/lists.cljs
Normal file
492
frontend/src/app/main/ui/workspace/tokens/sets/lists.cljs
Normal file
|
@ -0,0 +1,492 @@
|
|||
;; 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.sets.lists
|
||||
(:require-macros [app.main.style :as stl])
|
||||
(:require
|
||||
[app.common.data.macros :as dm]
|
||||
[app.common.types.tokens-lib :as ctob]
|
||||
[app.main.data.workspace.tokens.library-edit :as dwtl]
|
||||
[app.main.store :as st]
|
||||
[app.main.ui.context :as ctx]
|
||||
[app.main.ui.ds.buttons.icon-button :refer [icon-button*]]
|
||||
[app.main.ui.ds.foundations.assets.icon :refer [icon*] :as ic]
|
||||
[app.main.ui.ds.foundations.typography.text :refer [text*]]
|
||||
[app.main.ui.hooks :as h]
|
||||
[app.main.ui.workspace.tokens.sets.helpers :as sets-helpers]
|
||||
[app.util.dom :as dom]
|
||||
[app.util.i18n :refer [tr]]
|
||||
[app.util.keyboard :as kbd]
|
||||
[cuerdas.core :as str]
|
||||
[rumext.v2 :as mf]))
|
||||
|
||||
(defn- on-start-creation
|
||||
[]
|
||||
(st/emit! (dwtl/start-token-set-creation [])))
|
||||
|
||||
(defn- group-edition-id
|
||||
"Prefix editing groups `edition-id` so it can be differentiated from sets with the same id."
|
||||
[edition-id]
|
||||
(str "group-" edition-id))
|
||||
|
||||
|
||||
(mf/defc editing-label*
|
||||
{::mf/private true}
|
||||
[{:keys [default-value on-cancel on-submit]}]
|
||||
(let [on-submit
|
||||
(mf/use-fn
|
||||
(mf/deps on-cancel on-submit default-value)
|
||||
(fn [event]
|
||||
(let [value (dom/get-target-val event)]
|
||||
(if (or (str/empty? value)
|
||||
(= value default-value))
|
||||
(on-cancel)
|
||||
(on-submit value)))))
|
||||
|
||||
on-key-down
|
||||
(mf/use-fn
|
||||
(mf/deps on-submit on-cancel)
|
||||
(fn [event]
|
||||
(cond
|
||||
(kbd/enter? event) (on-submit event)
|
||||
(kbd/esc? event) (on-cancel))))]
|
||||
[:input
|
||||
{:class (stl/css :editing-node)
|
||||
:type "text"
|
||||
:on-blur on-submit
|
||||
:on-key-down on-key-down
|
||||
:maxlength "256"
|
||||
:auto-focus true
|
||||
:placeholder (tr "workspace.tokens.set-edit-placeholder")
|
||||
:default-value default-value}]))
|
||||
|
||||
(mf/defc checkbox*
|
||||
[{:keys [checked aria-label on-click disabled]}]
|
||||
(let [all? (true? checked)
|
||||
mixed? (= checked "mixed")
|
||||
checked? (or all? mixed?)]
|
||||
|
||||
[:div {:role "checkbox"
|
||||
:aria-checked (dm/str checked)
|
||||
:disabled disabled
|
||||
:title (when disabled (tr "workspace.tokens.no-permisions-set"))
|
||||
:tab-index 0
|
||||
:class (stl/css-case :checkbox-style true
|
||||
:checkbox-checked-style checked?
|
||||
:checkbox-disabled-checked (and checked? disabled)
|
||||
:checkbox-disabled disabled)
|
||||
:on-click (when-not disabled on-click)}
|
||||
|
||||
(when ^boolean checked?
|
||||
[:> icon*
|
||||
{:aria-label aria-label
|
||||
:class (stl/css :check-icon)
|
||||
:size "s"
|
||||
:icon-id (if mixed? ic/remove ic/tick)}])]))
|
||||
|
||||
(mf/defc inline-add-button*
|
||||
[]
|
||||
(let [can-edit? (mf/use-ctx ctx/can-edit?)]
|
||||
(if can-edit?
|
||||
[:div {:class (stl/css :empty-sets-wrapper)}
|
||||
[:> text* {:as "span" :typography "body-small" :class (stl/css :empty-state-message)}
|
||||
(tr "workspace.tokens.no-sets-yet")]
|
||||
[:button {:on-click on-start-creation
|
||||
:class (stl/css :create-set-button)}
|
||||
(tr "workspace.tokens.create-one")]]
|
||||
[:div {:class (stl/css :empty-sets-wrapper)}
|
||||
[:> text* {:as "span" :typography "body-small" :class (stl/css :empty-state-message)}
|
||||
(tr "workspace.tokens.no-sets-yet")]])))
|
||||
|
||||
(mf/defc add-button*
|
||||
[]
|
||||
[:> icon-button* {:variant "ghost"
|
||||
:icon "add"
|
||||
:on-click on-start-creation
|
||||
:aria-label (tr "workspace.tokens.add set")}])
|
||||
|
||||
(mf/defc sets-tree-set-group*
|
||||
{::mf/private true}
|
||||
[{:keys [id label tree-depth tree-path is-active is-selected is-draggable is-collapsed tree-index on-drop
|
||||
on-toggle-collapse on-toggle is-editing on-start-edition on-reset-edition on-edit-submit]}]
|
||||
|
||||
(let [can-edit?
|
||||
(mf/use-ctx ctx/can-edit?)
|
||||
|
||||
label-id
|
||||
(str id "-label")
|
||||
|
||||
on-context-menu
|
||||
(mf/use-fn
|
||||
(mf/deps is-editing id tree-path can-edit?)
|
||||
(fn [event]
|
||||
(dom/prevent-default event)
|
||||
(dom/stop-propagation event)
|
||||
(when (and can-edit? (not is-editing))
|
||||
(st/emit! (dwtl/assign-token-set-context-menu
|
||||
{:position (dom/get-client-position event)
|
||||
:is-group true
|
||||
:id id
|
||||
:edition-id (group-edition-id id)
|
||||
:path tree-path})))))
|
||||
|
||||
on-collapse-click
|
||||
(mf/use-fn
|
||||
(fn [event]
|
||||
(dom/prevent-default event)
|
||||
(dom/stop-propagation event)
|
||||
(on-toggle-collapse tree-path)))
|
||||
|
||||
on-double-click
|
||||
(mf/use-fn (mf/deps id) #(on-start-edition (group-edition-id id)))
|
||||
|
||||
on-checkbox-click
|
||||
(mf/use-fn
|
||||
(mf/deps on-toggle tree-path can-edit?)
|
||||
#(on-toggle tree-path))
|
||||
|
||||
on-edit-submit'
|
||||
(mf/use-fn
|
||||
(mf/deps tree-path on-edit-submit can-edit?)
|
||||
#(on-edit-submit tree-path %))
|
||||
|
||||
on-drop
|
||||
(mf/use-fn
|
||||
(mf/deps tree-index on-drop)
|
||||
(fn [position data]
|
||||
(on-drop tree-index position data)))
|
||||
|
||||
[dprops dref]
|
||||
(h/use-sortable
|
||||
:data-type "penpot/token-set"
|
||||
:on-drop on-drop
|
||||
:data {:index tree-index
|
||||
:is-group true}
|
||||
:detect-center? true
|
||||
:draggable? is-draggable)]
|
||||
|
||||
[:div {:ref dref
|
||||
:data-testid "tokens-set-group-item"
|
||||
:style {"--tree-depth" tree-depth}
|
||||
:class (stl/css-case :set-item-container true
|
||||
:set-item-group true
|
||||
:selected-set is-selected
|
||||
:dnd-over (= (:over dprops) :center)
|
||||
:dnd-over-top (= (:over dprops) :top)
|
||||
:dnd-over-bot (= (:over dprops) :bot))
|
||||
:on-context-menu on-context-menu}
|
||||
[:> icon-button*
|
||||
{:class (stl/css :set-item-group-collapse-button)
|
||||
:on-click on-collapse-click
|
||||
:data-testid "tokens-set-group-collapse"
|
||||
:aria-label (tr "labels.collapse")
|
||||
:icon (if is-collapsed "arrow-right" "arrow-down")
|
||||
:variant "action"}]
|
||||
(if is-editing
|
||||
[:> editing-label*
|
||||
{:default-value label
|
||||
:on-cancel on-reset-edition
|
||||
:on-submit on-edit-submit'}]
|
||||
[:*
|
||||
[:div {:class (stl/css :set-name)
|
||||
:role "button"
|
||||
:title label
|
||||
:tab-index 0
|
||||
:on-double-click on-double-click
|
||||
:id label-id}
|
||||
label]
|
||||
[:> checkbox*
|
||||
{:on-click on-checkbox-click
|
||||
:disabled (not can-edit?)
|
||||
:checked (case is-active
|
||||
:all true
|
||||
:partial "mixed"
|
||||
:none false)
|
||||
:arial-label (tr "workspace.tokens.select-set")}]])]))
|
||||
|
||||
(mf/defc sets-tree-set*
|
||||
[{:keys [id set label tree-depth tree-path tree-index is-selected is-active is-draggable is-editing
|
||||
on-select on-drop on-toggle on-start-edition on-reset-edition on-edit-submit]}]
|
||||
|
||||
(let [set-name (get set :name)
|
||||
can-edit? (mf/use-ctx ctx/can-edit?)
|
||||
|
||||
on-click
|
||||
(mf/use-fn
|
||||
(mf/deps is-editing tree-path)
|
||||
(fn [event]
|
||||
(dom/stop-propagation event)
|
||||
(when-not is-editing
|
||||
(when (fn? on-select)
|
||||
(on-select set-name)))))
|
||||
|
||||
on-context-menu
|
||||
(mf/use-fn
|
||||
(mf/deps is-editing id tree-path can-edit?)
|
||||
(fn [event]
|
||||
(dom/prevent-default event)
|
||||
(dom/stop-propagation event)
|
||||
(when (and can-edit? (not is-editing))
|
||||
(st/emit! (dwtl/assign-token-set-context-menu
|
||||
{:position (dom/get-client-position event)
|
||||
:is-group false
|
||||
:id id
|
||||
:edition-id id
|
||||
:path tree-path})))))
|
||||
|
||||
on-double-click
|
||||
(mf/use-fn (mf/deps id) #(on-start-edition id))
|
||||
|
||||
on-checkbox-click
|
||||
(mf/use-fn
|
||||
(mf/deps set-name on-toggle)
|
||||
(fn [event]
|
||||
(dom/stop-propagation event)
|
||||
(when (fn? on-toggle)
|
||||
(on-toggle set-name))))
|
||||
|
||||
on-edit-submit'
|
||||
(mf/use-fn
|
||||
(mf/deps set on-edit-submit)
|
||||
#(on-edit-submit set %))
|
||||
|
||||
on-drag
|
||||
(mf/use-fn
|
||||
(mf/deps tree-path)
|
||||
(fn [_]
|
||||
(when-not is-selected
|
||||
(on-select tree-path))))
|
||||
|
||||
on-drop
|
||||
(mf/use-fn
|
||||
(mf/deps tree-index on-drop)
|
||||
(fn [position data]
|
||||
(on-drop tree-index position data)))
|
||||
|
||||
[dprops dref]
|
||||
(h/use-sortable
|
||||
:data-type "penpot/token-set"
|
||||
:on-drag on-drag
|
||||
:on-drop on-drop
|
||||
:data {:index tree-index
|
||||
:is-group false}
|
||||
:draggable? is-draggable)
|
||||
|
||||
drop-over
|
||||
(get dprops :over)]
|
||||
|
||||
[:div {:ref dref
|
||||
:role "button"
|
||||
:data-testid "tokens-set-item"
|
||||
:style {"--tree-depth" tree-depth}
|
||||
:class (stl/css-case :set-item-container true
|
||||
:selected-set is-selected
|
||||
:dnd-over (= drop-over :center)
|
||||
:dnd-over-top (= drop-over :top)
|
||||
:dnd-over-bot (= drop-over :bot))
|
||||
:on-click on-click
|
||||
:on-double-click on-double-click
|
||||
:on-context-menu on-context-menu
|
||||
:aria-checked is-active}
|
||||
|
||||
[:> icon*
|
||||
{:icon-id "document"
|
||||
:class (stl/css-case :icon true
|
||||
:root-icon (not tree-depth))}]
|
||||
(if is-editing
|
||||
[:> editing-label*
|
||||
{:default-value label
|
||||
:on-cancel on-reset-edition
|
||||
:on-submit on-edit-submit'}]
|
||||
[:*
|
||||
[:div {:class (stl/css :set-name)}
|
||||
label]
|
||||
[:> checkbox*
|
||||
{:on-click on-checkbox-click
|
||||
:disabled (not can-edit?)
|
||||
:arial-label (tr "workspace.tokens.select-set")
|
||||
:checked is-active}]])]))
|
||||
|
||||
(mf/defc token-sets-tree*
|
||||
[{:keys [is-draggable
|
||||
selected
|
||||
is-token-set-group-active
|
||||
is-token-set-active
|
||||
on-start-edition
|
||||
on-reset-edition
|
||||
on-edit-submit-set
|
||||
on-edit-submit-group
|
||||
on-select
|
||||
on-toggle-set
|
||||
on-toggle-set-group
|
||||
token-sets
|
||||
new-path
|
||||
edition-id]}]
|
||||
|
||||
(let [collapsed-paths* (mf/use-state #{})
|
||||
collapsed-paths (deref collapsed-paths*)
|
||||
|
||||
collapsed?
|
||||
(mf/use-fn
|
||||
(mf/deps collapsed-paths)
|
||||
(partial contains? collapsed-paths))
|
||||
|
||||
on-drop
|
||||
(mf/use-fn
|
||||
(mf/deps collapsed-paths)
|
||||
(fn [tree-index position data]
|
||||
(let [params {:from-index (:index data)
|
||||
:to-index tree-index
|
||||
:position position
|
||||
:collapsed-paths collapsed-paths}]
|
||||
(if (:is-group data)
|
||||
(st/emit! (dwtl/drop-token-set-group params))
|
||||
(st/emit! (dwtl/drop-token-set params))))))
|
||||
|
||||
on-toggle-collapse
|
||||
(mf/use-fn
|
||||
(fn [path]
|
||||
(swap! collapsed-paths* #(if (contains? % path)
|
||||
(disj % path)
|
||||
(conj % path)))))]
|
||||
|
||||
(for [{:keys [id token-set index is-new is-group path parent-path depth] :as node}
|
||||
(ctob/sets-tree-seq token-sets
|
||||
{:skip-children-pred collapsed?
|
||||
:new-at-path new-path})]
|
||||
(cond
|
||||
^boolean is-group
|
||||
[:> sets-tree-set-group*
|
||||
{:key index
|
||||
:label (peek path)
|
||||
:id id
|
||||
:is-active (is-token-set-group-active path)
|
||||
:is-selected false
|
||||
:is-draggable is-draggable
|
||||
:is-editing (= edition-id (group-edition-id id))
|
||||
:is-collapsed (collapsed? path)
|
||||
:on-select on-select
|
||||
|
||||
:tree-path path
|
||||
:tree-depth depth
|
||||
:tree-index index
|
||||
:tree-parent-path parent-path
|
||||
|
||||
:on-drop on-drop
|
||||
:on-start-edition on-start-edition
|
||||
:on-reset-edition on-reset-edition
|
||||
:on-edit-submit on-edit-submit-group
|
||||
:on-toggle-collapse on-toggle-collapse
|
||||
:on-toggle on-toggle-set-group}]
|
||||
|
||||
^boolean is-new
|
||||
[:> sets-tree-set*
|
||||
{:key index
|
||||
:set token-set
|
||||
:label ""
|
||||
:id id
|
||||
:is-editing true
|
||||
:is-active true
|
||||
:is-selected true
|
||||
|
||||
:tree-path path
|
||||
:tree-depth depth
|
||||
:tree-index index
|
||||
:tree-parent-path parent-path
|
||||
|
||||
:on-drop on-drop
|
||||
:on-reset-edition on-reset-edition
|
||||
:on-edit-submit sets-helpers/on-create-token-set}]
|
||||
|
||||
:else
|
||||
[:> sets-tree-set*
|
||||
{:key index
|
||||
:set token-set
|
||||
:id id
|
||||
:label (peek path)
|
||||
:is-editing (= edition-id id)
|
||||
:is-active (is-token-set-active id)
|
||||
:is-selected (= selected id)
|
||||
:is-draggable is-draggable
|
||||
:on-select on-select
|
||||
:tree-path path
|
||||
:tree-depth depth
|
||||
:tree-index index
|
||||
:tree-parent-path parent-path
|
||||
:on-toggle on-toggle-set
|
||||
:edition-id edition-id
|
||||
:on-start-edition on-start-edition
|
||||
:on-drop on-drop
|
||||
:on-reset-edition on-reset-edition
|
||||
:on-edit-submit on-edit-submit-set}]))))
|
||||
|
||||
(mf/defc controlled-sets-list*
|
||||
{::mf/props :obj}
|
||||
[{:keys [token-sets
|
||||
selected
|
||||
on-update-token-set
|
||||
on-update-token-set-group
|
||||
is-token-set-active
|
||||
is-token-set-group-active
|
||||
on-create-token-set
|
||||
on-toggle-token-set
|
||||
on-toggle-token-set-group
|
||||
on-start-edition
|
||||
on-reset-edition
|
||||
origin
|
||||
on-select
|
||||
new-path
|
||||
edition-id]}]
|
||||
|
||||
(assert (fn? is-token-set-group-active) "expected a function for `is-token-set-group-active` prop")
|
||||
(assert (fn? is-token-set-active) "expected a function for `is-token-set-active` prop")
|
||||
|
||||
(let [theme-modal? (= origin "theme-modal")
|
||||
can-edit? (mf/use-ctx ctx/can-edit?)
|
||||
draggable? (and (not theme-modal?) can-edit?)
|
||||
empty-state? (and theme-modal?
|
||||
(empty? token-sets)
|
||||
(not new-path))
|
||||
|
||||
;; NOTE: on-reset-edition and on-start-edition function can
|
||||
;; come as nil, in this case we need to provide a safe
|
||||
;; fallback for them
|
||||
on-reset-edition
|
||||
(mf/use-fn
|
||||
(mf/deps on-reset-edition)
|
||||
(fn [v]
|
||||
(when (fn? on-reset-edition)
|
||||
(on-reset-edition v))))
|
||||
|
||||
on-start-edition
|
||||
(mf/use-fn
|
||||
(mf/deps on-start-edition)
|
||||
(fn [v]
|
||||
(when (fn? on-start-edition)
|
||||
(on-start-edition v))))]
|
||||
|
||||
[:div {:class (stl/css :sets-list)}
|
||||
(if ^boolean empty-state?
|
||||
[:> text* {:as "span" :typography "body-small" :class (stl/css :empty-state-message-sets)}
|
||||
(tr "workspace.tokens.no-sets-create")]
|
||||
|
||||
[:> token-sets-tree*
|
||||
{:is-draggable draggable?
|
||||
:new-path new-path
|
||||
:edition-id edition-id
|
||||
:token-sets token-sets
|
||||
:selected selected
|
||||
:on-select on-select
|
||||
:is-token-set-active is-token-set-active
|
||||
:is-token-set-group-active is-token-set-group-active
|
||||
:on-toggle-set on-toggle-token-set
|
||||
:on-toggle-set-group on-toggle-token-set-group
|
||||
:on-create-token-set on-create-token-set
|
||||
:on-start-edition on-start-edition
|
||||
:on-reset-edition on-reset-edition
|
||||
:on-edit-submit-set on-update-token-set
|
||||
:on-edit-submit-group on-update-token-set-group}])]))
|
164
frontend/src/app/main/ui/workspace/tokens/sets/lists.scss
Normal file
164
frontend/src/app/main/ui/workspace/tokens/sets/lists.scss
Normal file
|
@ -0,0 +1,164 @@
|
|||
// 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 *;
|
||||
@import "refactor/common-refactor.scss";
|
||||
|
||||
.sets-list {
|
||||
width: 100%;
|
||||
margin-bottom: 0;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.empty-sets-wrapper {
|
||||
padding: $s-12;
|
||||
padding-inline-start: $s-24;
|
||||
color: var(--color-foreground-secondary);
|
||||
}
|
||||
|
||||
.create-set-button {
|
||||
@include use-typography("body-small");
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
appearance: none;
|
||||
color: var(--color-accent-primary);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.set-item-container {
|
||||
@include bodySmallTypography;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
min-height: $s-32;
|
||||
cursor: pointer;
|
||||
color: var(--layer-row-foreground-color);
|
||||
padding-left: calc($s-24 * var(--tree-depth, 0) + $s-8);
|
||||
border: $s-2 solid transparent;
|
||||
gap: $s-2;
|
||||
|
||||
&.dnd-over-bot {
|
||||
border-bottom: $s-2 solid var(--layer-row-foreground-color-hover);
|
||||
}
|
||||
&.dnd-over-top {
|
||||
border-top: $s-2 solid var(--layer-row-foreground-color-hover);
|
||||
}
|
||||
&.dnd-over {
|
||||
border: $s-2 solid var(--layer-row-foreground-color-hover);
|
||||
}
|
||||
}
|
||||
|
||||
.set-item-group {
|
||||
cursor: unset;
|
||||
padding-left: calc($s-24 * var(--tree-depth, 0));
|
||||
gap: 0;
|
||||
}
|
||||
|
||||
.set-item-group-collapse-button {
|
||||
cursor: pointer;
|
||||
width: auto;
|
||||
height: $s-28;
|
||||
}
|
||||
|
||||
.set-name {
|
||||
@include textEllipsis;
|
||||
flex-grow: 1;
|
||||
padding-left: $s-2;
|
||||
}
|
||||
|
||||
.icon {
|
||||
flex-shrink: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
width: $s-20;
|
||||
height: $s-20;
|
||||
padding-right: $s-4;
|
||||
}
|
||||
|
||||
.root-icon {
|
||||
margin-left: $s-8;
|
||||
}
|
||||
|
||||
.checkbox-style {
|
||||
flex-shrink: 0;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: $s-16;
|
||||
height: $s-16;
|
||||
margin-inline: $s-6;
|
||||
background-color: var(--input-checkbox-background-color-rest);
|
||||
border: $s-1 solid var(--input-checkbox-border-color-rest);
|
||||
border-radius: $s-4;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.checkbox-checked-style {
|
||||
background-color: var(--input-border-color-active);
|
||||
color: var(--color-background-secondary);
|
||||
}
|
||||
|
||||
.checkbox-disabled {
|
||||
border: $s-1 solid var(--color-background-quaternary);
|
||||
background-color: var(--color-background-tertiary);
|
||||
}
|
||||
|
||||
.checkbox-disabled-checked {
|
||||
background-color: var(--color-accent-primary-muted);
|
||||
color: var(--color-background-quaternary);
|
||||
}
|
||||
|
||||
.check-icon {
|
||||
color: currentColor;
|
||||
}
|
||||
|
||||
.set-item-container:hover {
|
||||
background-color: var(--layer-row-background-color-hover);
|
||||
color: var(--layer-row-foreground-color-hover);
|
||||
box-shadow: -100px 0 0 0 var(--layer-row-background-color-hover);
|
||||
}
|
||||
|
||||
.empty-state-message-sets {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
padding: $s-12;
|
||||
color: var(--color-foreground-secondary);
|
||||
}
|
||||
.selected-set {
|
||||
background-color: var(--layer-row-background-color-selected);
|
||||
color: var(--layer-row-foreground-color-selected);
|
||||
box-shadow: -100px 0 0 0 var(--layer-row-background-color-selected);
|
||||
}
|
||||
|
||||
.collapsabled-icon {
|
||||
@include buttonStyle;
|
||||
@include flexCenter;
|
||||
height: $s-24;
|
||||
border-radius: $br-8;
|
||||
&:hover {
|
||||
color: var(--title-foreground-color-hover);
|
||||
}
|
||||
}
|
||||
|
||||
.editing-node {
|
||||
@include textEllipsis;
|
||||
@include bodySmallTypography;
|
||||
@include removeInputStyle;
|
||||
|
||||
border: $s-1 solid var(--input-border-color-focus);
|
||||
border-radius: $br-8;
|
||||
color: var(--layer-row-foreground-color-focus);
|
||||
flex-grow: 1;
|
||||
height: $s-28;
|
||||
margin: 0;
|
||||
padding-left: $s-6;
|
||||
|
||||
&::placeholder {
|
||||
color: var(--layer-row-foreground-color-placeholder);
|
||||
}
|
||||
}
|
|
@ -29,7 +29,8 @@
|
|||
[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.sets :as tsets]
|
||||
[app.main.ui.workspace.tokens.sets-context-menu :refer [token-set-context-menu*]]
|
||||
[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]
|
||||
|
@ -188,7 +189,7 @@
|
|||
(not token-set-new-path))
|
||||
|
||||
(when-not token-set-new-path
|
||||
[:> tsets/inline-add-button*])
|
||||
[:> tsetslist/inline-add-button*])
|
||||
|
||||
[:> h/sortable-container {}
|
||||
[:> tsets/sets-list*
|
||||
|
@ -197,7 +198,7 @@
|
|||
:edition-id token-set-edition-id
|
||||
:selected selected-token-set-name}]])))
|
||||
|
||||
(mf/defc token-sets-section*
|
||||
(mf/defc token-management-section*
|
||||
{::mf/private true}
|
||||
[{:keys [resize-height] :as props}]
|
||||
|
||||
|
@ -206,17 +207,16 @@
|
|||
|
||||
[:*
|
||||
[:> token-set-context-menu*]
|
||||
[:article {:data-testid "token-themes-sets-sidebar"
|
||||
:class (stl/css :sets-section-wrapper)
|
||||
[:section {:data-testid "token-management-sidebar"
|
||||
:class (stl/css :token-management-section-wrapper)
|
||||
:style {"--resize-height" (str resize-height "px")}}
|
||||
[:div {:class (stl/css :sets-sidebar)}
|
||||
[:> themes-header*]
|
||||
[:div {:class (stl/css :sidebar-header)}
|
||||
[:& title-bar {:title (tr "labels.sets")}
|
||||
(when can-edit?
|
||||
[:> tsets/add-button*])]]
|
||||
[:> tsetslist/add-button*])]]
|
||||
|
||||
[:> token-sets-list* props]]]]))
|
||||
[:> token-sets-list* props]]]))
|
||||
|
||||
(mf/defc tokens-section*
|
||||
[{:keys [tokens-lib]}]
|
||||
|
@ -398,7 +398,7 @@
|
|||
(mf/deref refs/tokens-lib)]
|
||||
|
||||
[:div {:class (stl/css :sidebar-wrapper)}
|
||||
[:> token-sets-section*
|
||||
[:> token-management-section*
|
||||
{:resize-height size-pages-opened
|
||||
:tokens-lib tokens-lib}]
|
||||
[:article {:class (stl/css :tokens-section-wrapper)
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
overflow: hidden;
|
||||
}
|
||||
|
||||
.sets-section-wrapper {
|
||||
.token-management-section-wrapper {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex: 1;
|
||||
|
@ -25,6 +25,8 @@
|
|||
flex-direction: column;
|
||||
overflow-y: auto;
|
||||
scrollbar-gutter: stable;
|
||||
position: relative;
|
||||
padding-block-end: var(--sp-l);
|
||||
}
|
||||
|
||||
.tokens-section-wrapper {
|
||||
|
@ -34,11 +36,6 @@
|
|||
scrollbar-gutter: stable;
|
||||
}
|
||||
|
||||
.sets-sidebar {
|
||||
position: relative;
|
||||
padding-block-end: var(--sp-l);
|
||||
}
|
||||
|
||||
.sets-header-container {
|
||||
@include use-typography("headline-small");
|
||||
padding: var(--sp-s);
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
[app.main.ui.ds.foundations.typography.heading :refer [heading*]]
|
||||
[app.main.ui.ds.foundations.typography.text :refer [text*]]
|
||||
[app.main.ui.icons :as i]
|
||||
[app.main.ui.workspace.tokens.sets :as wts]
|
||||
[app.main.ui.workspace.tokens.sets.lists :as wts]
|
||||
[app.util.dom :as dom]
|
||||
[app.util.i18n :refer [tr]]
|
||||
[app.util.keyboard :as k]
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue