diff --git a/frontend/src/app/main/ui/workspace/tokens/sets.cljs b/frontend/src/app/main/ui/workspace/tokens/sets.cljs new file mode 100644 index 000000000..01a2c212e --- /dev/null +++ b/frontend/src/app/main/ui/workspace/tokens/sets.cljs @@ -0,0 +1,101 @@ +;; 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 + (:require-macros [app.main.style :as stl]) + (:require + [app.common.data.macros :as dm] + [app.main.store :as st] + [app.main.ui.icons :as i] + [app.util.dom :as dom] + [okulary.core :as l] + [potok.v2.core :as ptk] + [rumext.v2 :as mf])) + +(def active-sets #{#uuid "2858b330-828e-4131-86ed-e4d1c0f4b3e3" + #uuid "d608877b-842a-473b-83ca-b5f8305caf83"}) + +(def sets-root-order [#uuid "2858b330-828e-4131-86ed-e4d1c0f4b3e3" + #uuid "9c5108aa-bdb4-409c-a3c8-c3dfce2f8bf8" + #uuid "0381446e-1f1d-423f-912c-ab577d61b79b"]) + +(def sets {#uuid "9c5108aa-bdb4-409c-a3c8-c3dfce2f8bf8" {:type :group + :name "Group A" + :children [#uuid "d1754e56-3510-493f-8287-5ef3417d4141" + #uuid "d608877b-842a-473b-83ca-b5f8305caf83"]} + #uuid "d608877b-842a-473b-83ca-b5f8305caf83" {:type :set + :name "Set A / 1"} + #uuid "d1754e56-3510-493f-8287-5ef3417d4141" {:type :group + :name "Group A / B" + :children [#uuid "f608877b-842a-473b-83ca-b5f8305caf83" + #uuid "7cc05389-9391-426e-bc0e-ba5cb8f425eb"]} + #uuid "f608877b-842a-473b-83ca-b5f8305caf83" {:type :set + :name "Set A / B / 1"} + #uuid "7cc05389-9391-426e-bc0e-ba5cb8f425eb" {:type :set + :name "Set A / B / 2"} + #uuid "2858b330-828e-4131-86ed-e4d1c0f4b3e3" {:type :set + :name "Set Root 1"} + #uuid "0381446e-1f1d-423f-912c-ab577d61b79b" {:type :set + :name "Set Root 2"}}) + +(def ^:private chevron-icon + (i/icon-xref :arrow (stl/css :chevron-icon))) + +(defn set-selected-set + [set-id] + (dm/assert! (uuid? set-id)) + (ptk/reify ::set-selected-set + ptk/UpdateEvent + (update [_ state] + (assoc state :selected-set-id set-id)))) + +(mf/defc sets-tree + [{:keys [selected-set-id set-id]}] + (let [set (get sets set-id)] + (when set + (let [{:keys [type name children]} set + visible? (mf/use-state (contains? active-sets set-id)) + collapsed? (mf/use-state false) + icon (if (= type :set) i/document i/group) + selected? (mf/use-state (= set-id selected-set-id)) + + on-click + (mf/use-fn + (mf/deps type set-id) + (fn [event] + (dom/stop-propagation event) + (st/emit! (set-selected-set set-id))))] + [:div {:class (stl/css :set-item-container) + :on-click on-click} + [:div {:class (stl/css-case :set-item-group (= type :group) + :set-item-set (= type :set) + :selected-set (and (= type :set) @selected?))} + (when (= type :group) + [:span {:class (stl/css-case + :collapsabled-icon true + :collapsed @collapsed?) + :on-click #(when (= type :group) (swap! collapsed? not))} + chevron-icon]) + [:span {:class (stl/css :icon)} icon] + [:div {:class (stl/css :set-name)} name] + (when (= type :set) + [:span {:class (stl/css :action-btn) + :on-click #(swap! visible? not)} + (if @visible? + i/shown + i/hide)])] + (when (and children (not @collapsed?)) + [:div {:class (stl/css :set-children)} + (for [child-id children] + [:& sets-tree {:key child-id :set-id child-id :selected-set-id selected-set-id}])])])))) + +(mf/defc sets-list + [{:keys [selected-set-id]}] + [:ul {:class (stl/css :sets-list)} + (for [set-id sets-root-order] + [:& sets-tree {:key set-id + :set-id set-id + :selected-set-id selected-set-id}])]) diff --git a/frontend/src/app/main/ui/workspace/tokens/sets.scss b/frontend/src/app/main/ui/workspace/tokens/sets.scss new file mode 100644 index 000000000..5c32bf199 --- /dev/null +++ b/frontend/src/app/main/ui/workspace/tokens/sets.scss @@ -0,0 +1,101 @@ +// 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 + +@import "refactor/common-refactor.scss"; + +.sets-list { + width: 100%; + margin-bottom: $s-12; + overflow-y: auto; +} + +.set-item-container { + width: 100%; + cursor: pointer; + color: var(--layer-row-foreground-color); + padding-left: $s-20; +} + +.set-item-set, +.set-item-group { + @include bodySmallTypography; + display: flex; + align-items: center; + min-height: $s-32; + width: 100%; + cursor: pointer; + color: var(--layer-row-foreground-color); + .set-name { + @include textEllipsis; + flex-grow: 1; + padding-left: $s-2; + } + + .icon { + display: flex; + align-items: center; + width: $s-20; + height: $s-20; + padding-right: $s-4; + + svg { + height: $s-20; + width: $s-20; + color: white; + fill: none; + stroke: var(--icon-foreground); + } + } +} + +.set-item-set { + &: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); + } +} + +.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); +} + +.action-btn { + @extend .button-tertiary; + height: $s-28; + width: $s-28; + svg { + @extend .button-icon; + width: 12px; + height: 12px; + } +} + +.collapsabled-icon { + @include buttonStyle; + @include flexCenter; + height: $s-24; + border-radius: $br-8; + + --chevron-icon-rotation: 90deg; + + &.collapsed { + --chevron-icon-rotation: 0deg; + } + + &:hover { + --chevron-icon-color: var(--title-foreground-color-hover); + } +} + +.chevron-icon { + @extend .button-icon-small; + margin-right: $s-6; + transform: rotate(var(--chevron-icon-rotation)); + stroke: var(--icon-foreground); +} diff --git a/frontend/src/app/main/ui/workspace/tokens/sidebar.cljs b/frontend/src/app/main/ui/workspace/tokens/sidebar.cljs index 7cab3ea9a..7729f41df 100644 --- a/frontend/src/app/main/ui/workspace/tokens/sidebar.cljs +++ b/frontend/src/app/main/ui/workspace/tokens/sidebar.cljs @@ -12,11 +12,13 @@ [app.main.data.tokens :as dt] [app.main.refs :as refs] [app.main.store :as st] + [app.main.ui.components.title-bar :refer [title-bar]] [app.main.ui.icons :as i] [app.main.ui.workspace.sidebar.assets.common :as cmm] [app.main.ui.workspace.tokens.changes :as wtch] [app.main.ui.workspace.tokens.context-menu :refer [token-context-menu]] [app.main.ui.workspace.tokens.core :as wtc] + [app.main.ui.workspace.tokens.sets :refer [sets-list]] [app.main.ui.workspace.tokens.style-dictionary :as sd] [app.main.ui.workspace.tokens.token :as wtt] [app.main.ui.workspace.tokens.token-types :as wtty] @@ -32,6 +34,9 @@ (def ^:private download-icon (i/icon-xref :download (stl/css :download-icon))) +(def selected-set-id + (l/derived :selected-set-id st/state)) + (mf/defc token-pill {::mf/wrap-props false} [{:keys [on-click token highlighted? on-context-menu]}] @@ -166,13 +171,35 @@ :tokens tokens :token-type-props token-type-props}])]])) +(mf/defc sets-sidebar + [] + (let [selected-set-id (mf/deref selected-set-id) + open? (mf/use-state true)] + [:div {:class (stl/css :sets-sidebar)} + [:div {:class (stl/css :sidebar-header)} + [:& title-bar {:collapsable true + :collapsed (not @open?) + :all-clickable true + :title "SETS" + :on-collapsed #(swap! open? not)}] + [:button {:class (stl/css :add-set) + :on-click #(println "Add Set")} + i/add]] + (when @open? + [:& sets-list {:selected-set-id selected-set-id}])])) + (mf/defc tokens-sidebar-tab {::mf/wrap [mf/memo] ::mf/wrap-props false} [_props] - [:div {:class (stl/css :sidebar-tab-wrapper)} - [:& tokens-explorer] - [:button {:class (stl/css :download-json-button) - :on-click wtc/download-tokens-as-json} - download-icon - "Export JSON"]]) + (let [show-sets-section? false] ;; temporarily added this variable to see/hide the sets section till we have it working end to end + [:div {:class (stl/css :sidebar-tab-wrapper)} + (when show-sets-section? + [:div {:class (stl/css :sets-section-wrapper)} + [:& sets-sidebar]]) + [:div {:class (stl/css :tokens-section-wrapper)} + [:& tokens-explorer]] + [:button {:class (stl/css :download-json-button) + :on-click wtc/download-tokens-as-json} + download-icon + "Export JSON"]])) diff --git a/frontend/src/app/main/ui/workspace/tokens/sidebar.scss b/frontend/src/app/main/ui/workspace/tokens/sidebar.scss index 67ff95ee0..e90b12d3c 100644 --- a/frontend/src/app/main/ui/workspace/tokens/sidebar.scss +++ b/frontend/src/app/main/ui/workspace/tokens/sidebar.scss @@ -5,11 +5,57 @@ // Copyright (c) KALEIDOS INC @import "refactor/common-refactor.scss"; - @import "./common.scss"; .sidebar-tab-wrapper { - padding: $s-12; + display: flex; + flex-direction: column; + height: 100%; + overflow: hidden; +} + +.sets-section-wrapper { + display: flex; + flex-direction: column; + margin-bottom: $s-8; +} + +.sets-sidebar { + position: relative; +} + +.sidebar-header { + display: flex; + align-items: center; + justify-content: space-between; + margin-left: $s-8; + padding-top: $s-12; + color: var(--layer-row-foreground-color); +} + +.add-set { + @extend .button-tertiary; + height: $s-32; + width: $s-28; + padding: 0; + margin-right: $s-12; + svg { + @extend .button-icon; + stroke: var(--icon-foreground); + transform: rotate(90deg); + } +} + +.tokens-section-wrapper { + flex: 1; + padding-top: $s-12; + padding-left: $s-12; + overflow-y: auto; +} + +// TODO Remove once sets are available to public +.sets-section-wrapper + .tokens-section-wrapper { + padding-top: 0; } .token-pills-wrapper {