🐛 Add a tokens source icon to libraries section (#11439)

* 🐛 Add a tokens source icon to libraries section

* 🐛 Fix ellipsis on library names

* ♻️ Remove code under flag on legacy component

* 🐛 Fix token theme name on inspect tab
This commit is contained in:
Eva Marco 2026-09-01 15:49:50 +02:00 committed by Andrés Moya
parent b101a16c70
commit dcf90f9e28
12 changed files with 171 additions and 127 deletions

View File

@ -57,6 +57,7 @@
.icon {
color: var(--arrow-icon-color);
flex-shrink: 0;
}
.title-wrapper {

View File

@ -313,7 +313,8 @@
"A collection of all icons"
(collect-icons))
(def ^:private ^:const icon-size-l 32)
(def ^:private ^:const icon-size-xl 32)
(def ^:private ^:const icon-size-l 24)
(def ^:private ^:const icon-size-m 16)
(def ^:private ^:const icon-size-s 12)
@ -322,12 +323,13 @@
[:class {:optional true} [:maybe :string]]
[:icon-id [:and :string [:fn #(contains? icon-list %)]]]
[:size {:optional true}
[:maybe [:enum "s" "m" "l"]]]])
[:maybe [:enum "s" "m" "l" "xl"]]]])
(mf/defc icon*
{::mf/schema schema:icon}
[{:keys [icon-id size class] :rest props}]
(let [size-px (cond (= size "l") icon-size-l
(let [size-px (cond (= size "xl") icon-size-xl
(= size "l") icon-size-l
(= size "s") icon-size-s
:else icon-size-m)
offset (if (or (= size "s") (= size "m"))

View File

@ -25,6 +25,6 @@
(when icon
[:div {:class (stl/css :icon-wrapper)}
[:> icon* {:icon-id icon
:size "l"
:size "xl"
:class (stl/css :icon)}]])
[:div {:class (stl/css :text)} text]]))

View File

@ -113,7 +113,10 @@
tokens-lib (mf/deref refs/tokens-lib)
tokens-status (mf/deref refs/tokens-status)
active-themes (mf/deref refs/workspace-active-theme-ids)
active-theme-ids (mf/deref refs/workspace-active-theme-ids)
active-themes (mf/with-memo [active-theme-ids tokens-lib]
(when tokens-lib
(keep #(some-> (ctob/get-theme tokens-lib %) ctob/get-name) active-theme-ids)))
active-sets (mf/with-memo [tokens-status tokens-lib]
(when (and tokens-status tokens-lib)
(cfo/get-active-sets tokens-status tokens-lib)))
@ -156,7 +159,7 @@
(when (or (seq active-themes) (seq active-sets))
[:li
[:> style-box* {:panel :token}
[:> tokens-panel* {:theme-paths active-themes :set-names (map ctob/get-name active-sets)}]]])
[:> tokens-panel* {:theme-names active-themes :set-names (map ctob/get-name active-sets)}]]])
(for [panel panels]
[:li {:key (d/name panel)}
(case panel

View File

@ -13,10 +13,10 @@
[rumext.v2 :as mf]))
(mf/defc tokens-panel*
[{:keys [theme-paths set-names]}]
[{:keys [theme-names set-names]}]
[:div {:class (stl/css :tokens-panel)}
(when (seq theme-paths)
(let [theme-list (str/join ", " theme-paths)]
(when (seq theme-names)
(let [theme-list (str/join ", " theme-names)]
[:> properties-row* {:class (stl/css :token-theme)
:term (tr "inspect.tabs.styles.active-themes")
:detail theme-list}]))

View File

@ -370,13 +370,6 @@
:tokens/import-from-library {:file-id file-id
:library-id library-id})))))
set-as-tokens-source
(mf/use-fn
(fn [event]
(let [library-id (some-> (dom/get-current-target event)
(dom/get-data "library-id")
(uuid/parse))]
(st/emit! (dwtl/set-tokens-source library-id)))))
on-delete-accept
(mf/use-fn
@ -430,16 +423,7 @@
[:div {:class (stl/css :item-content)}
[:div {:class (stl/css :item-title)} (tr "workspace.libraries.file-library")]
[:ul {:class (stl/css :item-contents-legacy)}
[:> library-description* {:summary summary}]]
(when (contains? cf/flags :token-lib-sync)
(if (cfo/effective-tokens-source? local-library (:id local-library))
[:div (tr "workspace.libraries.tokens-source")]
(when (not= (cfo/get-tokens-source local-library) (:id local-library))
[:> button* {:variant "secondary"
:type "button"
:data-library-id (dm/str (:id local-library))
:on-click set-as-tokens-source}
(tr "workspace.libraries.set-as-tokens-source")])))]
[:> library-description* {:summary summary}]]]
(if ^boolean is-shared
[:> button* {:variant "secondary"
@ -460,8 +444,7 @@
:key (dm/str id)
:data-testid "library-item"}
[:div {:class (stl/css :item-content)}
[:div {:class (stl/css-case :item-name true
:item-name-short has-tokens?)} name]
[:div {:class (stl/css :item-name)} name]
[:ul {:class (stl/css :item-contents-legacy)}
(let [summary (get-library-summary data)]
[:*
@ -470,28 +453,17 @@
[:div {:class (stl/css :connected-to-wrapper-legacy)}
[:span "(" (tr "workspace.libraries.connected-to") " "]
[:span {:class (stl/css :connected-to-values)} (str/join ", " connected-to-names)]
[:span ")"]])])]
(when (contains? cf/flags :token-lib-sync)
(when (cfo/effective-tokens-source? local-library id)
[:div (tr "workspace.libraries.tokens-source")]))]
[:span ")"]])])]]
[:div {:class (stl/css :library-actions)}
(if (contains? cf/flags :token-lib-sync)
(when (and (cfo/tokens-provider? (:data library))
(not (cfo/effective-tokens-source? local-library id)))
[:> button* {:variant "secondary"
:type "button"
:data-library-id (dm/str id)
:on-click set-as-tokens-source}
(tr "workspace.libraries.set-as-tokens-source")])
(when ^boolean has-tokens?
[:> icon-button*
{:type "button"
:aria-label (tr "workspace.tokens.import-tokens")
:icon i/import-export
:data-library-id (dm/str id)
:variant "secondary"
:on-click import-tokens}]))
(when ^boolean has-tokens?
[:> icon-button*
{:type "button"
:aria-label (tr "workspace.tokens.import-tokens")
:icon i/import-export
:data-library-id (dm/str id)
:variant "secondary"
:on-click import-tokens}])
[:> icon-button* {:type "button"
:aria-label (tr "workspace.libraries.unlink-library-btn")
@ -875,8 +847,7 @@
:key (dm/str id)
:data-testid "library-item"}
[:div {:class (stl/css :item-content)}
[:div {:class (stl/css-case :item-name true
:item-name-short has-tokens?)} name]
[:div {:class (stl/css :item-name)} name]
[:ul {:class (stl/css :item-contents)}
(let [summary (get-library-summary data)]
[:> library-description* {:summary summary :hint-name parent-name}])]]
@ -1017,7 +988,7 @@
[:div {:class (stl/css :section-list-item)
:key (dm/str id)}
[:div {:class (stl/css :item-content)}
[:div {:class (stl/css :item-name-long)} name]
[:div {:class (stl/css :item-name)} name]
[:ul {:class (stl/css :item-contents)} (describe-library
(count components)
0

View File

@ -97,7 +97,7 @@
%section-list-item-placeholder {
display: grid;
grid-template-columns: 1fr auto;
grid-template-columns: minmax(0, 1fr) auto;
align-items: center;
gap: var(--sp-s);
border: $b-1 solid var(--color-background-quaternary);
@ -108,7 +108,7 @@
.section-list-publish {
@extend %section-list-item-placeholder;
grid-template-columns: 1fr auto auto;
grid-template-columns: minmax(0, 1fr) auto auto;
border: none;
}
@ -129,11 +129,12 @@
.section-list-item-double-icon {
@extend %section-list-item-placeholder;
grid-template-columns: 1fr auto auto;
grid-template-columns: minmax(0, 1fr) auto auto;
}
.item-content {
height: fit-content;
min-width: 0;
}
.close-btn {
@ -253,7 +254,6 @@
@include text-ellipsis;
margin: 0;
max-width: px2rem(236);
color: var(--library-name-foreground-color);
}
@ -261,16 +261,6 @@
@extend %item-name;
}
.item-name-short {
max-width: px2rem(206);
}
.item-name-long {
@extend %item-name;
max-width: px2rem(450);
}
.item-title {
@include t.use-typography("body-large");
@ -308,6 +298,7 @@
.library-actions {
display: flex;
flex-shrink: 0;
gap: var(--sp-xs);
}

View File

@ -8,6 +8,7 @@
(:require-macros [app.main.style :as stl])
(:require
[app.common.data.macros :as dm]
[app.common.files.tokens :as cfo]
[app.common.types.components-list :as ctkl]
[app.main.data.modal :as modal]
[app.main.data.workspace :as dw]
@ -33,6 +34,12 @@
[{:keys [filters]}]
(let [file-id (mf/use-ctx ctx/current-file-id)
files (mf/deref refs/files)
current-file-data
(mf/deref refs/workspace-data)
tokens-source
(mf/with-memo [current-file-data]
(cfo/get-effective-tokens-source current-file-data))
libraries (mf/with-memo [files file-id]
(->> (refs/select-libraries files file-id)
(vals)
@ -46,6 +53,7 @@
{:key (dm/str (:id file))
:file file
:is-local false
:is-tokens-source (= (:id file) tokens-source)
:is-default-open false
:filters filters}])))
@ -57,11 +65,16 @@
(mf/defc assets-local-library*
{::mf/private true}
[{:keys [filters]}]
(let [file (mf/deref ref:local-library)]
(let [file (mf/deref ref:local-library)
is-tokens-source
(mf/with-memo [file]
(cfo/effective-tokens-source? (:data file) (:id file)))]
[:> file-library*
{:file file
:is-local true
:is-default-open true
:is-tokens-source is-tokens-source
:filters filters}]))
(defn- toggle-values

View File

@ -22,7 +22,8 @@
[app.main.store :as st]
[app.main.ui.components.title-bar :refer [title-bar*]]
[app.main.ui.context :as ctx]
[app.main.ui.icons :as deprecated-icon]
[app.main.ui.ds.foundations.assets.icon :as i :refer [icon*]]
[app.main.ui.ds.tooltip :refer [tooltip*]]
[app.main.ui.workspace.sidebar.assets.colors :refer [colors-section*]]
[app.main.ui.workspace.sidebar.assets.common :as cmm]
[app.main.ui.workspace.sidebar.assets.components :refer [components-section*]]
@ -76,7 +77,7 @@
(mf/defc file-library-title*
{::mf/private true}
[{:keys [is-open is-local file-id page-id file-name]}]
[{:keys [is-open is-local file-id page-id file-name is-tokens-source]}]
(let [router (mf/deref refs/router)
team-id (mf/use-ctx ctx/current-team-id)
url (rt/resolve router :workspace
@ -93,7 +94,15 @@
(mf/use-fn
(fn [ev]
(dom/stop-propagation ev)
(st/emit! (ev/event {::ev/name "navigate-to-library-file"}))))]
(st/emit! (ev/event {::ev/name "navigate-to-library-file"}))))
tokens-source-icon
(when is-tokens-source
(mf/html [:> tooltip* {:content (tr "workspace.tokens.current-tokens-source-tooltip")}
[:span {:class (stl/css :tokens-source-icon-wrapper)}
[:> icon* {:icon-id i/tokens
:size "m"
:class (stl/css :tokens-source-icon)}]]]))]
[:div {:class (stl/css-case
:library-title true
@ -103,17 +112,24 @@
:on-collapsed toggle-open
:title (if is-local
(mf/html [:div {:class (stl/css :special-title)}
(tr "workspace.assets.local-library")])
[:span {:class (stl/css :special-title-text)}
(tr "workspace.assets.local-library")]
tokens-source-icon])
;; Do we need to add shared info here?
(mf/html [:div {:class (stl/css :special-title)}
file-name]))}
[:span {:class (stl/css :special-title-text)}
file-name]
tokens-source-icon]))}
(when-not ^boolean is-local
[:span {:title (tr "workspace.assets.open-library")}
[:a {:class (stl/css :file-link)
:href (str "#" url)
:target "_blank"
:on-click on-click}
deprecated-icon/open-link]])]]))
[:> icon* {:icon-id i/open-link
:size "m"
:class (stl/css :file-link-icon)}]]])]]))
(defn- extend-selected
[selected type asset-groups asset-id file-id]
@ -299,13 +315,15 @@
(not ^boolean show-colors?)
(not ^boolean show-typography?))
[:div {:class (stl/css :asset-title)}
[:span {:class (stl/css :no-found-icon)}
deprecated-icon/search]
[:span {:class (stl/css :no-found-icon-wrapper)}
[:> icon* {:icon-id i/search
:size "l"
:class (stl/css :no-found-icon)}]]
[:span {:class (stl/css :no-found-text)}
(tr "workspace.assets.not-found")]])])]))
(mf/defc file-library*
[{:keys [file is-local is-default-open filters]}]
[{:keys [file is-local is-default-open filters is-tokens-source]}]
(let [file-id (:id file)
file-name (:name file)
page-id (dm/get-in file [:data :pages 0])
@ -381,7 +399,8 @@
:page-id page-id
:file-name file-name
:is-open open?
:is-local is-local}]
:is-local is-local
:is-tokens-source is-tokens-source}]
(when ^boolean open?
[:> file-library-content*

View File

@ -4,95 +4,131 @@
//
// Copyright (c) KALEIDOS SUBSIDIARY SL
@use "ds/typography.scss" as t;
@use "refactor/common-refactor.scss" as deprecated;
@use "ds/_borders.scss" as *;
@use "ds/_sizes.scss" as *;
@use "ds/_utils.scss" as *;
@use "ds/typography.scss" as *;
.tool-window {
padding: 0 0 deprecated.$s-24 deprecated.$s-12;
padding-inline-start: var(--sp-m);
padding-block-end: var(--sp-xxl);
display: grid;
grid-auto-rows: max-content;
gap: deprecated.$s-4;
height: 100%;
}
.file-name {
@include t.use-typography("body-small");
display: flex;
justify-content: flex-start;
align-items: center;
flex-grow: 100;
height: 100%;
gap: var(--sp-xs);
block-size: 100%;
}
.loading {
@include t.use-typography("body-small");
@include use-typography("body-small");
display: flex;
align-items: center;
justify-content: flex-start;
height: deprecated.$s-32;
padding-left: calc(deprecated.$s-12 + deprecated.$s-2);
block-size: $sz-32;
padding-inline-start: calc(var(--sp-m) + var(--sp-xxs));
color: var(--color-foreground-secondary);
}
.special-title {
@include deprecated.text-ellipsis;
color: var(--title-foreground-color-hover);
margin-left: deprecated.$s-2;
box-sizing: border-box;
inline-size: 100%;
min-inline-size: 0;
display: flex;
align-items: center;
gap: var(--sp-xs);
color: var(--color-foreground-primary);
padding-inline-start: var(--sp-xxs);
text-align: left;
}
.special-title-text {
display: block;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.tokens-source-icon-wrapper {
display: inline-flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
border: $b-1 solid var(--color-accent-select);
border-radius: $br-4;
padding: var(--sp-xxs);
}
.tokens-source-icon {
flex-shrink: 0;
color: var(--color-accent-tertiary);
}
.file-link {
@extend %button-tertiary;
--file-link-background-color: transparent;
--file-link-border-color: transparent;
--file-link-foreground-color: var(--color-foreground-secondary);
height: deprecated.$s-32;
width: deprecated.$s-28;
border-radius: deprecated.$br-8;
display: grid;
place-content: center;
block-size: $sz-32;
inline-size: $sz-28;
border: $b-2 solid var(--file-link-border-color);
border-radius: $br-8;
background-color: var(--file-link-background-color);
color: var(--file-link-foreground-color);
cursor: pointer;
svg {
@extend %button-icon;
&:hover {
--file-link-background-color: var(--color-background-quaternary);
--file-link-border-color: var(--color-background-quaternary);
--file-link-foreground-color: var(--color-accent-primary);
}
stroke: var(--icon-foreground);
fill: var(--title-foreground-color-hover);
&:active {
--file-link-background-color: var(--color-background-secondary);
--file-link-border-color: transparent;
--file-link-foreground-color: var(--color-accent-primary);
outline: none;
}
&:focus-visible {
--file-link-background-color: var(--color-background-tertiary);
--file-link-foreground-color: var(--color-foreground-primary);
outline: none;
border: $b-1 solid var(--color-accent-primary);
}
}
.library-content {
width: 100%;
inline-size: 100%;
display: grid;
grid-auto-rows: max-content;
gap: deprecated.$s-4;
gap: var(--sp-xs);
}
.asset-title {
margin-left: deprecated.$s-28;
margin-inline-start: px2rem(28);
display: flex;
flex-direction: column;
align-items: center;
gap: deprecated.$s-8;
gap: var(--sp-s);
}
.no-found-icon {
@include deprecated.flex-center;
background-color: var(--not-found-background-color);
border-radius: deprecated.$br-circle;
height: deprecated.$s-48;
width: deprecated.$s-48;
svg {
@extend %button-icon;
height: deprecated.$s-24;
width: deprecated.$s-24;
stroke: var(--not-found-foreground-color);
}
.no-found-icon-wrapper {
display: flex;
align-items: center;
justify-content: center;
background-color: var(--color-background-tertiary);
border-radius: $br-circle;
block-size: $sz-48;
inline-size: $sz-48;
color: var(--color-foreground-secondary);
}
.no-found-text {
@include deprecated.body-small-typography;
@include use-typography("body-small");
color: var(--not-found-foreground-color);
color: var(--color-foreground-secondary);
}

View File

@ -10151,6 +10151,10 @@ msgstr "The value is not valid"
msgid "workspace.tokens.connected-library"
msgstr "connected library"
#: src/app/main/ui/workspace/sidebar/assets/file_library.cljs:102
msgid "workspace.tokens.current-tokens-source-tooltip"
msgstr "This is the current Tokens source"
#: src/app/main/ui/workspace/tokens/tokens_source.cljs:25
msgid "workspace.tokens.open-connected-library"
msgstr "Open connected library"

View File

@ -9808,6 +9808,10 @@ msgstr "El valor no es válido"
msgid "workspace.tokens.connected-library"
msgstr "librería conectada"
#: src/app/main/ui/workspace/sidebar/assets/file_library.cljs:102
msgid "workspace.tokens.current-tokens-source-tooltip"
msgstr "Esta es la actual fuente de Tokens"
#: src/app/main/ui/workspace/tokens/tokens_source.cljs:25
msgid "workspace.tokens.open-connected-library"
msgstr "Abrir librería conectada"