0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-01-06 14:50:20 -05:00

♻️ Review sets code and add DS components

This commit is contained in:
Eva Marco 2024-10-25 14:54:00 +02:00 committed by Andrés Moya
parent bef648a63f
commit bc3ab8981e
10 changed files with 273 additions and 176 deletions

View file

@ -314,19 +314,23 @@
:on-toggle-dropdown on-toggle-dropdown
:theme theme
:on-change-field on-change-field}]
[:> text* {:as "span" :typography "body-small" :class (stl/css :select-sets-message)}
(tr "workspace.token.set-selection-theme")]
[:div {:class (stl/css :sets-list-wrapper)}
[:& wts/controlled-sets-list
{:token-sets token-sets
:token-set-selected? (constantly false)
:token-set-active? token-set-active?
:on-select on-toggle-token-set
:on-toggle-token-set on-toggle-token-set
:origin "theme-modal"
:context sets-context/static-context}]]
[:div {:class (stl/css :edit-theme-footer)}
[:> button* {:variant "secondary"
:type "button"
:icon "delete"
:on-click on-delete-token}
(tr "labels.delete")]
[:div {:class (stl/css :button-footer)}

View file

@ -83,6 +83,10 @@
color: var(--color-foreground-primary);
}
.select-sets-message {
color: var(--color-foreground-secondary);
}
.create-theme-wrapper {
display: flex;
flex-direction: column;

View file

@ -11,27 +11,23 @@
[app.main.data.tokens :as wdt]
[app.main.refs :as refs]
[app.main.store :as st]
[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.icons :as i]
[app.main.ui.workspace.tokens.sets-context :as sets-context]
[app.util.dom :as dom]
[app.util.i18n :refer [tr]]
[app.util.keyboard :as kbd]
[cuerdas.core :as str]
[rumext.v2 :as mf]))
(def ^:private chevron-icon
(i/icon-xref :arrow (stl/css :chevron-icon)))
(defn on-toggle-token-set-click [token-set-name]
(st/emit! (wdt/toggle-token-set {:token-set-name token-set-name})))
(defn on-select-token-set-click [name]
(st/emit! (wdt/set-selected-token-set-id name)))
(defn on-delete-token-set-click [name event]
(dom/stop-propagation event)
(st/emit! (wdt/delete-token-set name)))
(defn on-update-token-set [set-name token-set]
(st/emit! (wdt/update-token-set set-name token-set)))
@ -82,7 +78,7 @@
editing-node? (editing? name)
on-click
(mf/use-callback
(mf/use-fn
(mf/deps editing-node?)
(fn [event]
(dom/stop-propagation event)
@ -90,7 +86,7 @@
(on-select name))))
on-context-menu
(mf/use-callback
(mf/use-fn
(mf/deps editing-node? name)
(fn [event]
(dom/prevent-default event)
@ -114,6 +110,24 @@
(fn [position data]
(st/emit! (wdt/move-token-set (:name data) name position))))
on-submit-edit
(mf/use-fn
(mf/deps on-submit token-set)
#(on-submit (assoc token-set :name %)))
on-edit-name
(mf/use-fn
(fn [e]
(let [name (-> (dom/get-current-target e)
(dom/get-data "name"))]
(on-edit name))))
on-toggle-set (fn [event]
(dom/stop-propagation event)
(on-toggle name))
on-collapse (mf/use-fn #(swap! collapsed? not))
[dprops dref]
(h/use-sortable
:data-type "penpot/token-set"
@ -122,40 +136,43 @@
:data {:name name}
:draggable? true)]
[:div {:ref dref
:role "button"
:class (stl/css-case :set-item-container true
:dnd-over (= (:over dprops) :center)
:dnd-over-top (= (:over dprops) :top)
:dnd-over-bot (= (:over dprops) :bot))
:on-click on-click
:on-double-click #(on-edit name)
:on-double-click on-edit-name
:on-context-menu on-context-menu
:data-name name}
[:div {:class (stl/css-case :set-item-group group?
:set-item-set set?
:selected-set selected?)}
(when group?
[:span {:class (stl/css-case :collapsabled-icon true
:collapsed @collapsed?)
:on-click #(swap! collapsed? not)}
chevron-icon])
[:span {:class (stl/css :icon)}
(if set? i/document i/group)]
[:> icon-button* {:on-click on-collapse
:aria-label (tr "labels.collapse")
:icon (if @collapsed?
"arrow-right"
"arrow-down")
:variant "action"}])
[:> icon* {:id (if set? "document" "group")
:class (stl/css :icon)}]
(if editing-node?
[:& editing-node {:default-value name
:on-submit #(on-submit (assoc token-set :name %))
:on-submit on-submit-edit
:on-cancel on-cancel}]
[:*
[:div {:class (stl/css :set-name)} name]
[:div {:class (stl/css :delete-set)}
[:button {:on-click #(on-delete-token-set-click name %)
:type "button"}
i/delete]]
(if set?
[:span {:class (stl/css :action-btn)
:on-click (fn [event]
(dom/stop-propagation event)
(on-toggle name))}
(if visible? i/shown i/hide)]
[:button {:on-click on-toggle-set
:class (stl/css-case :checkbox-style true
:checkbox-checked-style visible?)}
(when visible?
[:> icon* {:aria-label (tr "workspace.token.select-set")
:class (stl/css :check-icon)
:size "s"
:id ic/tick}])]
nil
#_(when (and children (not @collapsed?))
[:div {:class (stl/css :set-children)}
@ -166,7 +183,7 @@
:selected-set-id selected-token-set-id)])]))])]]))
(defn warn-on-try-create-token-set-group! []
(st/emit! (ntf/show {:content "Token Set grouping is not supported yet."
(st/emit! (ntf/show {:content (tr "workspace.token.grouping-set-alert")
:notification-type :toast
:type :warning
:timeout 3000})))
@ -178,55 +195,67 @@
token-set-active?
on-create-token-set
on-toggle-token-set
origin
on-select
context]
:as _props}]
(let [{:keys [editing? new? on-edit on-create on-reset] :as ctx} (or context (sets-context/use-context))
avoid-token-set-grouping #(str/replace % "/" "-")]
avoid-token-set-grouping #(str/replace % "/" "-")
submit-token
#(do
;; TODO: We don't support set grouping for now so we rename sets for now
(when (str/includes? (:name %) "/")
(warn-on-try-create-token-set-group!))
(on-create-token-set (update % :name avoid-token-set-grouping))
(on-reset))]
[:ul {:class (stl/css :sets-list)}
(for [token-set token-sets]
(when token-set
[:& sets-tree
{:key (:name token-set)
:token-set token-set
:token-set-selected? (if new? (constantly false) token-set-selected?)
:token-set-active? token-set-active?
:editing? editing?
:on-select on-select
:on-edit on-edit
:on-toggle on-toggle-token-set
:on-submit #(do
;; TODO: We don't support set grouping for now so we rename sets for now
(when (str/includes? (:name %) "/")
(warn-on-try-create-token-set-group!))
(on-update-token-set (avoid-token-set-grouping (:name token-set)) (update % :name avoid-token-set-grouping))
(on-reset))
:on-cancel on-reset}]))
(if (and
(= origin "theme-modal")
(empty? token-sets))
[:> text* {:as "span" :typography "body-small" :class (stl/css :empty-state-message-sets)}
(tr "workspace.token.no-sets-create")]
(for [token-set token-sets]
(when token-set
(let [update-token
#(do
;; TODO: We don't support set grouping for now so we rename sets for now
(when (str/includes? (:name %) "/")
(warn-on-try-create-token-set-group!))
(on-update-token-set (avoid-token-set-grouping (:name token-set)) (update % :name avoid-token-set-grouping))
(on-reset))]
[:& sets-tree
{:key (:name token-set)
:token-set token-set
:token-set-selected? (if new? (constantly false) token-set-selected?)
:token-set-active? token-set-active?
:editing? editing?
:on-select on-select
:on-edit on-edit
:on-toggle on-toggle-token-set
:on-submit update-token
:on-cancel on-reset}]))))
(when new?
[:& sets-tree {:token-set {:name ""}
:token-set-selected? (constantly true)
:token-set-active? (constantly true)
:editing? (constantly true)
:on-select (constantly nil)
:on-edit on-create
:on-submit #(do
;; TODO: We don't support set grouping for now so we rename sets for now
(when (str/includes? (:name %) "/")
(warn-on-try-create-token-set-group!))
(on-create-token-set (update % :name avoid-token-set-grouping))
(on-reset))
:on-cancel on-reset}])]))
[:& sets-tree
{:token-set {:name ""}
:token-set-selected? (constantly true)
:token-set-active? (constantly true)
:editing? (constantly true)
:on-select (constantly nil)
:on-edit on-create
:on-submit submit-token
:on-cancel on-reset}])]))
(mf/defc sets-list
[{:keys []}]
(let [token-sets (mf/deref refs/workspace-ordered-token-sets)
selected-token-set-id (mf/deref refs/workspace-selected-token-set-id)
token-set-selected? (mf/use-callback
token-set-selected? (mf/use-fn
(mf/deps token-sets selected-token-set-id)
(fn [set-name]
(= set-name selected-token-set-id)))
active-token-set-ids (mf/deref refs/workspace-active-set-names)
token-set-active? (mf/use-callback
token-set-active? (mf/use-fn
(mf/deps active-token-set-ids)
(fn [id]
(get active-token-set-ids id)))]
@ -235,6 +264,7 @@
:token-set-selected? token-set-selected?
:token-set-active? token-set-active?
:on-select on-select-token-set-click
:origin "set-panel"
:on-toggle-token-set on-toggle-token-set-click
:on-update-token-set on-update-token-set
:on-create-token-set on-create-token-set}]))

View file

@ -39,111 +39,79 @@
width: 100%;
cursor: pointer;
color: var(--layer-row-foreground-color);
padding-right: $s-2;
.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);
.delete-set {
visibility: visible;
}
}
.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;
}
.checkbox-style {
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: 1px solid var(--input-checkbox-border-color-rest);
border-radius: 0.25rem;
padding: 0;
}
.checkbox-checked-style {
background-color: var(--input-border-color-active);
}
.check-icon {
color: var(--color-background-secondary);
}
.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);
}
.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);
}
.delete-set {
@extend .button-tertiary;
height: $s-28;
width: $s-28;
visibility: hidden;
button {
@include buttonStyle;
@include flexCenter;
width: $s-24;
height: 100%;
svg {
@extend .button-icon-small;
height: $s-12;
width: $s-12;
color: transparent;
fill: none;
stroke: var(--icon-foreground);
}
}
}
.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);
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);
}
.editing-node {
@include textEllipsis;
color: var(--layer-row-foreground-color-focus);
}
input.editing-node {
.editing-node {
@include textEllipsis;
@include bodySmallTypography;
@include removeInputStyle;

View file

@ -1,3 +1,9 @@
;; 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-context
(:require
[rumext.v2 :as mf]))

View file

@ -1,3 +1,9 @@
;; 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-context-menu
(:require-macros [app.main.style :as stl])
(:require
@ -7,6 +13,7 @@
[app.main.ui.components.dropdown :refer [dropdown]]
[app.main.ui.workspace.tokens.sets-context :as sets-context]
[app.util.dom :as dom]
[app.util.i18n :refer [tr]]
[okulary.core :as l]
[rumext.v2 :as mf]))
@ -29,10 +36,12 @@
(mf/defc menu
[{:keys [token-set-name]}]
(let [{:keys [on-edit]} (sets-context/use-context)]
(let [{:keys [on-edit]} (sets-context/use-context)
edit-name (mf/use-fn #(on-edit token-set-name))
delete-set (mf/use-fn #(st/emit! (wdt/delete-token-set token-set-name)))]
[:ul {:class (stl/css :context-list)}
[:& menu-entry {:title "Rename" :on-click #(on-edit token-set-name)}]
[:& menu-entry {:title "Delete" :on-click #(st/emit! (wdt/delete-token-set token-set-name))}]]))
[:& menu-entry {:title (tr "labels.rename") :on-click edit-name}]
[:& menu-entry {:title (tr "labels.delete") :on-click delete-set}]]))
(mf/defc sets-context-menu
[]

View file

@ -19,6 +19,7 @@
[app.main.ui.components.dropdown-menu :refer [dropdown-menu dropdown-menu-item*]]
[app.main.ui.components.title-bar :refer [title-bar]]
[app.main.ui.ds.buttons.button :refer [button*]]
[app.main.ui.ds.buttons.icon-button :refer [icon-button*]]
[app.main.ui.ds.foundations.typography.text :refer [text*]]
[app.main.ui.hooks :as h]
[app.main.ui.hooks.resize :refer [use-resize-hook]]
@ -188,9 +189,11 @@
[:span {:class (stl/css :themes-header)} (tr "labels.themes")]
(if (empty? ordered-themes)
[:div {:class (stl/css :empty-theme-wrapper)}
[:> text* {:as "span" :typography "body-small"} (tr "workspace.token.no-themes")]
[:> text* {:as "span" :typography "body-small" :class (stl/css :empty-state-message)}
(tr "workspace.token.no-themes")]
[:button {:on-click open-modal
:class (stl/css :create-theme-button)} (tr "workspace.token.create-a-theme")]]
:class (stl/css :create-theme-button)}
(tr "workspace.token.create-one")]]
[:div {:class (stl/css :theme-select-wrapper)}
[:& theme-select]
[:> button* {:variant "secondary"
@ -198,17 +201,24 @@
(tr "labels.edit")]])]))
(mf/defc add-set-button
[{:keys [on-open]}]
(let [{:keys [on-create]} (sets-context/use-context)]
[:button {:class (stl/css :add-set)
:on-click #(do
(on-open)
(on-create))}
i/add]))
[{:keys [on-open style]}]
(let [{:keys [on-create]} (sets-context/use-context)
on-click #(do
(on-open)
(on-create))]
(if (= style "inline")
[:button {:on-click on-click
:class (stl/css :create-theme-button)}
(tr "workspace.token.create-one")]
[:> icon-button* {:variant "ghost"
:icon "add"
:on-click on-click
:aria-label (tr "workspace.token.add set")}])))
(mf/defc themes-sets-tab
[]
(let [open? (mf/use-state true)
(let [token-sets (mf/deref refs/workspace-ordered-token-sets)
open? (mf/use-state true)
on-open (mf/use-fn #(reset! open? true))]
[:& sets-context/provider {}
[:& sets-context-menu]
@ -220,10 +230,18 @@
:all-clickable true
:title (tr "labels.sets")
:on-collapsed #(swap! open? not)}
[:& add-set-button {:on-open on-open}]]]
[:& add-set-button {:on-open on-open
:style "header"}]]]
(when @open?
[:& h/sortable-container {}
[:& sets-list]])]]))
[:*
(when (empty? token-sets)
[:div {:class (stl/css :empty-sets-wrapper)}
[:> text* {:as "span" :typography "body-small" :class (stl/css :empty-state-message)}
(tr "workspace.token.no-sets-yet")]
[:& add-set-button {:on-open on-open
:style "inline"}]])
[:& sets-list]]])]]))
(mf/defc tokens-tab
[_props]

View file

@ -55,6 +55,12 @@
color: var(--color-foreground-secondary);
}
.empty-sets-wrapper {
padding: $s-12;
padding-inline-start: $s-24;
color: var(--color-foreground-secondary);
}
.sidebar-header {
display: flex;
align-items: center;
@ -64,17 +70,8 @@
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);
}
.empty-state-message {
color: var(--color-foreground-secondary);
}
.token-pills-wrapper {

View file

@ -1532,6 +1532,10 @@ msgstr "Canva"
msgid "labels.close"
msgstr "Close"
#: src/app/main/ui/workspace/tokens/sets.cljs
msgid "labels.collapse"
msgstr "Collapse"
#: src/app/main/ui/dashboard/comments.cljs:104, src/app/main/ui/viewer/comments.cljs:70, src/app/main/ui/workspace/comments.cljs:126
msgid "labels.comments"
msgstr "Comments"
@ -6170,9 +6174,13 @@ msgid "workspace.token.no-themes"
msgstr "There are no themes."
#: src/app/main/ui/workspace/tokens/sidebar.cljs
msgid "workspace.token.create-a-theme"
msgid "workspace.token.create-one"
msgstr "Create one."
#: src/app/main/ui/workspace/tokens/sidebar.cljs
msgid "workspace.token.add set"
msgstr "Add set"
#: src/app/main/ui/workspace/tokens/modals/themes.cljs
msgid "workspace.token.save-theme"
msgstr "Save theme"
@ -6211,7 +6219,7 @@ msgstr "Theme %s"
#: src/app/main/ui/workspace/tokens/modals/themes.cljs
msgid "workspace.token.no-sets"
msgstr "No sets defined"
msgstr "No sets"
#: src/app/main/ui/workspace/tokens/modals/themes.cljs
msgid "workspace.token.num-sets"
@ -6231,4 +6239,24 @@ msgstr "No theme active"
#: src/app/main/ui/workspace/tokens/theme_select.cljs
msgid "workspace.token.active-themes"
msgstr "%s active themes"
msgstr "%s active themes"
#: src/app/main/ui/workspace/tokens/sets.cljs
msgid "workspace.token.grouping-set-alert"
msgstr "Token Set grouping is not supported yet."
#: src/app/main/ui/workspace/tokens/sets.cljs
msgid "workspace.token.select-set"
msgstr "Select set."
#: src/app/main/ui/workspace/tokens/sets.cljs
msgid msgid "workspace.token.set-selection-theme"
msgstr "Define what token sets should be used as part of this theme option:"
#: src/app/main/ui/workspace/tokens/sets.cljs
msgid "workspace.token.no-sets-yet"
msgstr "There are no sets yet."
#: src/app/main/ui/workspace/tokens/sets.cljs
msgid "workspace.token.no-sets-create"
msgstr "There are no sets defined yet. Create one first."

View file

@ -1534,6 +1534,10 @@ msgstr "Canva"
msgid "labels.close"
msgstr "Cerrar"
#: src/app/main/ui/workspace/tokens/sets.cljs
msgid "labels.collapse"
msgstr "Colapsar"
#: src/app/main/ui/dashboard/comments.cljs:104, src/app/main/ui/viewer/comments.cljs:70, src/app/main/ui/workspace/comments.cljs:126
msgid "labels.comments"
msgstr "Comentarios"
@ -6157,9 +6161,13 @@ msgid "workspace.token.no-themes"
msgstr "No hay temas."
#: src/app/main/ui/workspace/tokens/sidebar.cljs
msgid "workspace.token.create-a-theme"
msgid "workspace.token.create-one"
msgstr "Crear uno."
#: src/app/main/ui/workspace/tokens/sidebar.cljs
msgid "workspace.token.add set"
msgstr "Añadir set"
#: src/app/main/ui/workspace/tokens/modals/themes.cljs
msgid "workspace.token.save-theme"
msgstr "Guardar tema"
@ -6198,7 +6206,7 @@ msgstr "Tema %s"
#: src/app/main/ui/workspace/tokens/modals/themes.cljs
msgid "workspace.token.no-sets"
msgstr "No hay sets definidos"
msgstr "No hay sets"
#: src/app/main/ui/workspace/tokens/modals/themes.cljs
msgid "workspace.token.num-sets"
@ -6218,4 +6226,29 @@ msgstr "No hay temas activos"
#: src/app/main/ui/workspace/tokens/theme_select.cljs
msgid "workspace.token.active-themes"
msgstr "%s temas activos"
msgstr "%s temas activos"
#: src/app/main/ui/workspace/tokens/sets.cljs
msgid "workspace.token.grouping-set-alert"
msgstr "La agrupación de sets aun no está soportada."
#: src/app/main/ui/workspace/tokens/sets.cljs
msgid "workspace.token.select-set"
msgstr "Selecciona set"
#: src/app/main/ui/workspace/tokens/sets.cljs
msgid "workspace.token.set-selection-theme"
msgstr "Define que sets de tokens deberian formar parte de este tema:"
#: src/app/main/ui/workspace/tokens/sets.cljs
msgid "workspace.token.no-sets"
msgstr "Aun no hay sets."
#: src/app/main/ui/workspace/tokens/sets.cljs
msgid "workspace.create-one"
msgstr "Crea uno."
#: src/app/main/ui/workspace/tokens/sets.cljs
msgid "workspace.token.no-sets-create"
msgstr "Aun no hay sets definidos. Crea uno primero"