0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-01-21 06:02:32 -05:00

Merge pull request #256 from tokens-studio/token-sets-ui

Token sets UI
This commit is contained in:
Akshay Gupta 2024-08-20 22:14:51 +05:30 committed by GitHub
commit 93ce6b6eb3
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 283 additions and 8 deletions

View file

@ -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}])])

View file

@ -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);
}

View file

@ -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"]]))

View file

@ -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 {