diff --git a/frontend/resources/images/icons/broken-link.svg b/frontend/resources/images/icons/broken-link.svg
new file mode 100644
index 000000000..4e6ed1273
--- /dev/null
+++ b/frontend/resources/images/icons/broken-link.svg
@@ -0,0 +1,3 @@
+
diff --git a/frontend/resources/images/icons/token-status-full.svg b/frontend/resources/images/icons/token-status-full.svg
new file mode 100644
index 000000000..a24ba0ce7
--- /dev/null
+++ b/frontend/resources/images/icons/token-status-full.svg
@@ -0,0 +1,8 @@
+
\ No newline at end of file
diff --git a/frontend/resources/images/icons/token-status-non-applied.svg b/frontend/resources/images/icons/token-status-non-applied.svg
new file mode 100644
index 000000000..6c9838f0a
--- /dev/null
+++ b/frontend/resources/images/icons/token-status-non-applied.svg
@@ -0,0 +1,8 @@
+
\ No newline at end of file
diff --git a/frontend/resources/images/icons/token-status-partial.svg b/frontend/resources/images/icons/token-status-partial.svg
new file mode 100644
index 000000000..de17718d2
--- /dev/null
+++ b/frontend/resources/images/icons/token-status-partial.svg
@@ -0,0 +1,8 @@
+
\ No newline at end of file
diff --git a/frontend/src/app/main/ui/dashboard/grid.cljs b/frontend/src/app/main/ui/dashboard/grid.cljs
index 4c72b6852..ccd9de197 100644
--- a/frontend/src/app/main/ui/dashboard/grid.cljs
+++ b/frontend/src/app/main/ui/dashboard/grid.cljs
@@ -180,7 +180,7 @@
[:& bc/color-bullet {:color {:color (:color color)
:id (:id color)
:opacity (:opacity color)}
- :mini? true}]
+ :mini true}]
[:div {:class (stl/css :name-block)}
[:span {:class (stl/css :color-name)} (:name color)]
(when-not (= (:name color) default-name)
diff --git a/frontend/src/app/main/ui/ds.cljs b/frontend/src/app/main/ui/ds.cljs
index 89f8a4961..dff48b329 100644
--- a/frontend/src/app/main/ui/ds.cljs
+++ b/frontend/src/app/main/ui/ds.cljs
@@ -16,6 +16,7 @@
[app.main.ui.ds.foundations.typography :refer [typography-list]]
[app.main.ui.ds.foundations.typography.heading :refer [heading*]]
[app.main.ui.ds.foundations.typography.text :refer [text*]]
+ [app.main.ui.ds.foundations.utilities.token.token-status :refer [token-status-icon* token-status-list]]
[app.main.ui.ds.layout.tab-switcher :refer [tab-switcher*]]
[app.main.ui.ds.notifications.toast :refer [toast*]]
[app.main.ui.ds.product.empty-placeholder :refer [empty-placeholder*]]
@@ -40,8 +41,10 @@
:Text text*
:TabSwitcher tab-switcher*
:Toast toast*
+ :TokenStatusIcon token-status-icon*
;; meta / misc
:meta #js {:icons (clj->js (sort icon-list))
+ :tokenStatus (clj->js (sort token-status-list))
:svgs (clj->js (sort raw-svg-list))
:typography (clj->js typography-list)}
:storybook #js {:StoryGrid sb/story-grid*
diff --git a/frontend/src/app/main/ui/ds/colors.scss b/frontend/src/app/main/ui/ds/colors.scss
index 6d0823c93..773ee1afc 100644
--- a/frontend/src/app/main/ui/ds/colors.scss
+++ b/frontend/src/app/main/ui/ds/colors.scss
@@ -22,6 +22,7 @@ $orange-950: #440806;
$red-200: #ffcada;
$red-400: #c80857;
+$red-500: #ff3277;
$red-950: #500124;
$pink-400: #ff6fe0;
@@ -33,6 +34,16 @@ $purple-700: #6911d4;
$purple-600-10: #8c33eb1a;
$purple-700-60: #6911d499;
+$aqua-200: #ddf7ff;
+$aqua-400: #77e1f3;
+$aqua-600: #59acbb;
+$aqua-800: #1d4464;
+
+$violet-300: #a7a9ff;
+$violet-600: #6c6dad;
+$violet-700: #484c74;
+$violet-800: #272941;
+
$blue-200: #bae3fd;
$blue-500: #0e9be9;
$blue-950: #082c49;
@@ -72,6 +83,7 @@ $grayish-red: #bfbfbf;
--color-background-warning: #{$orange-200};
--color-accent-error: #{$red-400};
--color-background-error: #{$red-200};
+ --color-foreground-error: #{$red-500};
--color-accent-info: #{$blue-500};
--color-background-info: #{$blue-200};
@@ -87,6 +99,11 @@ $grayish-red: #bfbfbf;
--color-overlay-default: #{$white-60};
--color-overlay-onboarding: #{$white-90};
--color-canvas: #{$grayish-red};
+
+ --color-token-background: #{$aqua-200};
+ --color-token-border: #{$aqua-400};
+ --color-token-accent: #{$aqua-600};
+ --color-token-foreground: #{$aqua-800};
}
:global(.default) {
@@ -104,6 +121,7 @@ $grayish-red: #bfbfbf;
--color-background-warning: #{$orange-950};
--color-accent-error: #{$red-400};
--color-background-error: #{$red-950};
+ --color-foreground-error: #{$red-500};
--color-accent-info: #{$blue-500};
--color-background-info: #{$blue-950};
@@ -119,4 +137,9 @@ $grayish-red: #bfbfbf;
--color-overlay-default: #{$gray-950-60};
--color-overlay-onboarding: #{$gray-950-90};
--color-canvas: #{$grayish-red};
+
+ --color-token-background: #{$violet-800};
+ --color-token-border: #{$violet-700};
+ --color-token-accent: #{$violet-600};
+ --color-token-foreground: #{$violet-300};
}
diff --git a/frontend/src/app/main/ui/ds/foundations/assets/icon.cljs b/frontend/src/app/main/ui/ds/foundations/assets/icon.cljs
index 6411cff7e..a08630a91 100644
--- a/frontend/src/app/main/ui/ds/foundations/assets/icon.cljs
+++ b/frontend/src/app/main/ui/ds/foundations/assets/icon.cljs
@@ -62,6 +62,7 @@
(def ^:icon-id boolean-flatten "boolean-flatten")
(def ^:icon-id boolean-intersection "boolean-intersection")
(def ^:icon-id boolean-union "boolean-union")
+(def ^:icon-id broken-link "broken-link")
(def ^:icon-id bug "bug")
(def ^:icon-id character-a "character-a")
(def ^:icon-id character-b "character-b")
diff --git a/frontend/src/app/main/ui/ds/foundations/utilities/token/token_status.cljs b/frontend/src/app/main/ui/ds/foundations/utilities/token/token_status.cljs
new file mode 100644
index 000000000..482087f0e
--- /dev/null
+++ b/frontend/src/app/main/ui/ds/foundations/utilities/token/token_status.cljs
@@ -0,0 +1,28 @@
+(ns app.main.ui.ds.foundations.utilities.token.token-status
+ (:require-macros
+ [app.common.data.macros :as dm]
+ [app.main.style :as stl])
+ (:require
+ [app.main.ui.ds.foundations.assets.icon :refer [collect-icons]]
+ [rumext.v2 :as mf]))
+
+(def ^:icon-id token-status-partial "token-status-partial")
+(def ^:icon-id token-status-full "token-status-full")
+(def ^:icon-id token-status-non-applied "token-status-non-applied")
+
+(def token-status-list "A collection of all status" (collect-icons))
+
+(def ^:private schema:token-status-icon
+ [:map
+ [:class {:optional true} :string]
+ [:id [:and :string [:fn #(contains? token-status-list %)]]]])
+
+(mf/defc token-status-icon*
+ {::mf/props :obj
+ ::mf/schema schema:token-status-icon}
+ [{:keys [id class] :rest props}]
+ (let [class (dm/str (or class "") " " (stl/css :token-icon))
+ props (mf/spread-props props {:class class :width "14px" :height "14px"})
+ offset 0]
+ [:> "svg" props
+ [:use {:href (dm/str "#icon-" id) :width "14px" :height "14px" :x offset :y offset}]]))
diff --git a/frontend/src/app/main/ui/ds/foundations/utilities/token/token_status.mdx b/frontend/src/app/main/ui/ds/foundations/utilities/token/token_status.mdx
new file mode 100644
index 000000000..5d4fe3b59
--- /dev/null
+++ b/frontend/src/app/main/ui/ds/foundations/utilities/token/token_status.mdx
@@ -0,0 +1,31 @@
+import { Canvas, Meta } from '@storybook/blocks';
+import * as TokenStatusIconStories from "./token_status.stories"
+
+
+
+# Token status icons
+
+## Technical notes
+
+There are some SVG that are not regular icons, and that are only
+meant to be used on token components.
+
+They represent the applied status of a token over a shape.
+
+The assets are located in the `frontend/resources/images/icons` folder.
+
+### Using asset IDs
+
+For convenience, icons IDs are available in the component namespace.
+
+```clj
+(ns app.main.ui.foo
+ (:require
+ [app.main.ui.ds.foundations.utilities.token.token-status :refer [token-status-icon*] :as ts]))
+```
+
+```clj
+[:> token-status-icon*
+ {:id ts/token-status-partial
+ :class (stl/css :token-pill-icon)}]
+```
diff --git a/frontend/src/app/main/ui/ds/foundations/utilities/token/token_status.scss b/frontend/src/app/main/ui/ds/foundations/utilities/token/token_status.scss
new file mode 100644
index 000000000..207b2236a
--- /dev/null
+++ b/frontend/src/app/main/ui/ds/foundations/utilities/token/token_status.scss
@@ -0,0 +1,10 @@
+// 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
+
+.token-icon {
+ fill: currentColor;
+ stroke: none;
+}
diff --git a/frontend/src/app/main/ui/ds/foundations/utilities/token/token_status.stories.jsx b/frontend/src/app/main/ui/ds/foundations/utilities/token/token_status.stories.jsx
new file mode 100644
index 000000000..84cce010c
--- /dev/null
+++ b/frontend/src/app/main/ui/ds/foundations/utilities/token/token_status.stories.jsx
@@ -0,0 +1,23 @@
+import * as React from "react";
+import Components from "@target/components";
+
+const { TokenStatusIcon } = Components;
+const { tokenStatus } = Components.meta;
+
+export default {
+ title: "Foundations/Utilities/TokenStatus",
+ component: TokenStatusIcon,
+ argTypes: {
+ id: {
+ options: tokenStatus,
+ control: { type: "select" },
+ },
+ },
+ render: ({ ...args }) => ,
+};
+
+export const Default = {
+ args: {
+ id: "token-status-full",
+ },
+};
diff --git a/frontend/src/app/main/ui/viewer/inspect/attributes/common.cljs b/frontend/src/app/main/ui/viewer/inspect/attributes/common.cljs
index b5c26b07f..99b32b9ee 100644
--- a/frontend/src/app/main/ui/viewer/inspect/attributes/common.cljs
+++ b/frontend/src/app/main/ui/viewer/inspect/attributes/common.cljs
@@ -70,7 +70,7 @@
[:div {:class (stl/css :bullet-wrapper)
:style #js {"--bullet-size" "16px"}}
[:& cb/color-bullet {:color color
- :mini? true}]]
+ :mini true}]]
[:div {:class (stl/css :format-wrapper)}
[:div {:class (stl/css :image-format)}
@@ -102,7 +102,7 @@
[:div {:class (stl/css :bullet-wrapper)
:style #js {"--bullet-size" "16px"}}
[:& cb/color-bullet {:color color
- :mini? true}]]
+ :mini true}]]
[:div {:class (stl/css :format-wrapper)}
(when-not (and on-change-format (or (:gradient color) image))
diff --git a/frontend/src/app/main/ui/workspace/color_palette_ctx_menu.cljs b/frontend/src/app/main/ui/workspace/color_palette_ctx_menu.cljs
index 17dbb9450..c62498ca6 100644
--- a/frontend/src/app/main/ui/workspace/color_palette_ctx_menu.cljs
+++ b/frontend/src/app/main/ui/workspace/color_palette_ctx_menu.cljs
@@ -44,7 +44,7 @@
:style #js {"--bullet-size" "20px"}}
(for [[i {:keys [color id gradient]}] (map-indexed vector (take 7 colors))]
[:& cb/color-bullet {:key (dm/str "color-" i)
- :mini? true
+ :mini true
:color {:color color :id id :gradient gradient}}])]]]))
[:li {:class (stl/css-case :file-library true
@@ -68,7 +68,7 @@
:style #js {"--bullet-size" "20px"}}
(for [[i color] (map-indexed vector (take 7 (vals file-colors)))]
[:& cb/color-bullet {:key (dm/str "color-" i)
- :mini? true
+ :mini true
:color color}])]]]
[:li {:class (stl/css :recent-colors true
@@ -90,5 +90,5 @@
:style #js {"--bullet-size" "20px"}}
(for [[idx color] (map-indexed vector (take 7 (reverse recent-colors)))]
[:& cb/color-bullet {:key (str "color-" idx)
- :mini? true
+ :mini true
:color color}])]]]]]))
diff --git a/frontend/src/app/main/ui/workspace/sidebar/assets/colors.cljs b/frontend/src/app/main/ui/workspace/sidebar/assets/colors.cljs
index 7f91cf495..5c38dab9a 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/assets/colors.cljs
+++ b/frontend/src/app/main/ui/workspace/sidebar/assets/colors.cljs
@@ -211,7 +211,7 @@
[:div {:class (stl/css :bullet-block)}
[:& cb/color-bullet {:color color
- :mini? true}]]
+ :mini true}]]
(if ^boolean editing?
[:input
diff --git a/frontend/src/app/main/ui/workspace/sidebar/assets/common.cljs b/frontend/src/app/main/ui/workspace/sidebar/assets/common.cljs
index 578d08af2..5d03f3cfe 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/assets/common.cljs
+++ b/frontend/src/app/main/ui/workspace/sidebar/assets/common.cljs
@@ -25,7 +25,7 @@
[app.main.ui.components.context-menu-a11y :refer [context-menu*]]
[app.main.ui.components.title-bar :refer [title-bar]]
[app.main.ui.context :as ctx]
- [app.main.ui.icons :as i]
+ [app.main.ui.ds.foundations.assets.icon :refer [icon*]]
[app.util.array :as array]
[app.util.dom :as dom]
[app.util.dom.dnd :as dnd]
@@ -119,14 +119,13 @@
:left (:left state)
:options options}])
-(mf/defc section-icon
- {::mf/wrap-props false}
- [{:keys [section]}]
+(defn section-icon
+ [section]
(case section
- :colors i/drop-icon
- :components i/component
- :typographies i/text-palette
- i/add))
+ :colors "drop"
+ :components "component"
+ :typographies "text-palette"
+ "add"))
(mf/defc asset-section
{::mf/wrap-props false}
@@ -151,7 +150,7 @@
(mf/html
[:span {:class (stl/css :title-name)}
[:span {:class (stl/css :section-icon)}
- [:& (or icon section-icon) {:section section}]]
+ [:> icon* {:id (or icon (section-icon section)) :size "s"}]]
[:span {:class (stl/css :section-name)}
title]
@@ -167,10 +166,12 @@
:all-clickable true
:on-collapsed on-collapsed
:add-icon-gap (= 0 assets-count)
- :class (stl/css-case :title-spacing open?)
:title title}
buttons]
- (when ^boolean open? content)]))
+ (when ^boolean (and (< 0 assets-count)
+ open?)
+ [:div {:class (stl/css-case :title-spacing open?)}
+ content])]))
(mf/defc asset-section-block
{::mf/wrap-props false}
diff --git a/frontend/src/app/main/ui/workspace/sidebar/assets/common.scss b/frontend/src/app/main/ui/workspace/sidebar/assets/common.scss
index bbc0c7d70..14ae8aa10 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/assets/common.scss
+++ b/frontend/src/app/main/ui/workspace/sidebar/assets/common.scss
@@ -39,7 +39,7 @@
}
.title-spacing {
- margin-bottom: $s-4;
+ padding-block-start: $s-4;
}
.asset-section.opened {
diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/rows/color_row.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/rows/color_row.cljs
index e513f1c0f..a5ca4ac79 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/options/rows/color_row.cljs
+++ b/frontend/src/app/main/ui/workspace/sidebar/options/rows/color_row.cljs
@@ -208,7 +208,7 @@
(nil? color-name) (assoc
:id nil
:file-id nil))
- :mini? true
+ :mini true
:on-click handle-click-color}]]
(cond
;; Rendering a color with ID
diff --git a/frontend/src/app/main/ui/workspace/tokens/form.cljs b/frontend/src/app/main/ui/workspace/tokens/form.cljs
index 0b089a277..bae45a303 100644
--- a/frontend/src/app/main/ui/workspace/tokens/form.cljs
+++ b/frontend/src/app/main/ui/workspace/tokens/form.cljs
@@ -9,7 +9,6 @@
(:require
[app.common.colors :as c]
[app.common.data :as d]
- [app.common.data.macros :as dm]
[app.common.types.tokens-lib :as ctob]
[app.main.data.modal :as modal]
[app.main.data.tokens :as dt]
@@ -191,10 +190,10 @@ Token names should only contain letters and digits separated by . characters.")}
empty-message? (or (nil? result-or-errors)
(wte/has-error-code? :error/empty-input errors))
message (cond
- empty-message? (dm/str (tr "workspace.token.resolved-value") "-")
+ empty-message? (tr "workspace.token.resolved-value" "-")
errors (->> (wte/humanize-errors errors)
(str/join "\n"))
- :else (dm/str (tr "workspace.token.resolved-value") result-or-errors))]
+ :else (tr "workspace.token.resolved-value" result-or-errors))]
[:> text* {:as "p"
:typography "body-small"
:class (stl/css-case :resolved-value true
diff --git a/frontend/src/app/main/ui/workspace/tokens/modals/themes.scss b/frontend/src/app/main/ui/workspace/tokens/modals/themes.scss
index 0bb41b365..a3bb43803 100644
--- a/frontend/src/app/main/ui/workspace/tokens/modals/themes.scss
+++ b/frontend/src/app/main/ui/workspace/tokens/modals/themes.scss
@@ -158,7 +158,6 @@
}
.sets-count-button {
- text-transform: lowercase;
padding: $s-6;
padding-left: $s-12;
}
diff --git a/frontend/src/app/main/ui/workspace/tokens/sidebar.cljs b/frontend/src/app/main/ui/workspace/tokens/sidebar.cljs
index be028c8cd..ba5c84950 100644
--- a/frontend/src/app/main/ui/workspace/tokens/sidebar.cljs
+++ b/frontend/src/app/main/ui/workspace/tokens/sidebar.cljs
@@ -14,7 +14,6 @@
[app.main.data.tokens :as dt]
[app.main.refs :as refs]
[app.main.store :as st]
- [app.main.ui.components.color-bullet :refer [color-bullet]]
[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*]]
@@ -22,7 +21,6 @@
[app.main.ui.ds.foundations.typography.text :refer [text*]]
[app.main.ui.hooks :as h]
[app.main.ui.hooks.resize :refer [use-resize-hook]]
- [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]]
@@ -33,12 +31,12 @@
[app.main.ui.workspace.tokens.style-dictionary :as sd]
[app.main.ui.workspace.tokens.theme-select :refer [theme-select]]
[app.main.ui.workspace.tokens.token :as wtt]
+ [app.main.ui.workspace.tokens.token-pill :refer [token-pill]]
[app.main.ui.workspace.tokens.token-types :as wtty]
[app.util.dom :as dom]
[app.util.i18n :refer [tr]]
[app.util.webapi :as wapi]
[beicon.v2.core :as rx]
- [cuerdas.core :as str]
[okulary.core :as l]
[rumext.v2 :as mf]
[shadow.resource]))
@@ -46,57 +44,30 @@
(def lens:token-type-open-status
(l/derived (l/in [:workspace-tokens :open-status]) st/state))
-(def ^:private download-icon
- (i/icon-xref :download (stl/css :download-icon)))
-
;; Components ------------------------------------------------------------------
-(mf/defc token-pill
- {::mf/wrap-props false}
- [{:keys [on-click token theme-token highlighted? on-context-menu]}]
- (let [{:keys [name value resolved-value errors]} token
- errors? (and (seq errors) (seq (:errors theme-token)))]
- [:button
- {:class (stl/css-case :token-pill true
- :token-pill-highlighted highlighted?
- :token-pill-invalid errors?)
- :title (cond
- errors? (sd/humanize-errors token)
- :else (->> [(str "Token: " name)
- (str (tr "workspace.token.original-value") value)
- (str (tr "workspace.token.resolved-value") resolved-value)]
- (str/join "\n")))
- :on-click on-click
- :on-context-menu on-context-menu
- :disabled errors?}
- (when-let [color (if (seq (ctob/find-token-value-references (:value token)))
- (or
- (wtt/resolved-value-hex theme-token)
- ;; Fallback when the current set is inactive and has a reference that resolves in this inactive set
- (wtt/resolved-value-hex token))
- (wtt/resolved-value-hex token))]
- [:& color-bullet {:color color
- :mini? true}])
- name]))
-
-(mf/defc token-section-icon
- {::mf/wrap-props false}
- [{:keys [type]}]
+(defn token-section-icon
+ [type]
(case type
- :border-radius i/corner-radius
- :numeric [:span {:class (stl/css :section-text-icon)} "123"]
- :color i/drop-icon
- :boolean i/boolean-difference
- :opacity [:span {:class (stl/css :section-text-icon)} "%"]
- :rotation i/rotation
- :spacing i/padding-extended
- :string i/text-mixed
- :stroke-width i/stroke-size
- :typography i/text
- ;; TODO: Add diagonal icon here when it's available
- :dimensions [:div {:style {:rotate "45deg"}} i/constraint-horizontal]
- :sizing [:div {:style {:rotate "45deg"}} i/constraint-horizontal]
- i/add))
+ :border-radius "corner-radius"
+ :color "drop"
+ :boolean "boolean-difference"
+ :opacity "percentage"
+ :rotation "rotation"
+ :spacing "padding-extended"
+ :string "text-mixed"
+ :stroke-width "stroke-size"
+ :typography "text"
+ :dimensions "expand"
+ :sizing "expand"
+ "add"))
+
+(defn attribute-actions [token selected-shapes attributes]
+ (let [ids-by-attributes (wtt/shapes-ids-by-applied-attributes token selected-shapes attributes)
+ shape-ids (into #{} (map :id selected-shapes))]
+ {:all-selected? (wtt/shapes-applied-all? ids-by-attributes shape-ids attributes)
+ :shape-ids shape-ids
+ :selected-pred #(seq (% ids-by-attributes))}))
(mf/defc token-component
[{:keys [type tokens selected-shapes token-type-props active-theme-tokens]}]
@@ -140,29 +111,37 @@
:token-type-props token-type-props})))))
tokens-count (count tokens)]
[:div {:on-click on-toggle-open-click}
- [:& cmm/asset-section {:icon (mf/fnc icon-wrapper []
- [:div {:class (stl/css :section-icon)}
- [:& token-section-icon {:type type}]])
+ [:& cmm/asset-section {:icon (token-section-icon type)
:title title
:assets-count tokens-count
:open? open?}
[:& cmm/asset-section-block {:role :title-button}
- [:button {:class (stl/css :action-button)
- :on-click on-popover-open-click
- :title (str "Add token: " title)}
- i/add]]
+ [:> icon-button* {:on-click on-popover-open-click
+ :variant "ghost"
+ :icon "add"
+ :aria-label (str "Add token: " title)}]]
(when open?
[:& cmm/asset-section-block {:role :content}
[:div {:class (stl/css :token-pills-wrapper)}
(for [token (sort-by :name tokens)]
- (let [theme-token (get active-theme-tokens (wtt/token-identifier token))]
+ (let [theme-token (get active-theme-tokens (wtt/token-identifier token))
+ multiple-selection (< 1 (count selected-shapes))
+ full-applied (:all-selected? (attribute-actions token selected-shapes (or all-attributes attributes)))
+ applied (wtt/shapes-token-applied? token selected-shapes (or all-attributes attributes))
+ on-token-click (fn [e]
+ (on-token-pill-click e token))
+ on-context-menu (fn [e] (on-context-menu e token))]
[:& token-pill
{:key (:name token)
:token token
:theme-token theme-token
- :highlighted? (wtt/shapes-token-applied? token selected-shapes (or all-attributes attributes))
- :on-click #(on-token-pill-click % token)
- :on-context-menu #(on-context-menu % token)}]))]])]]))
+ :half-applied (and applied (not full-applied))
+ ;; Multiple selected shapes behavior should be reviewed after MVP
+ :full-applied (if multiple-selection
+ false
+ applied)
+ :on-click on-token-click
+ :on-context-menu on-context-menu}]))]])]]))
(defn sorted-token-groups
"Separate token-types into groups of `:empty` or `:filled` depending if tokens exist for that type.
@@ -270,24 +249,13 @@
[:& token-context-menu]
[:& title-bar {:all-clickable true
:title "TOKENS"}]
- [:div.assets-bar
- (for [{:keys [token-key token-type-props tokens]} (concat (:filled token-groups)
- (:empty token-groups))]
- [:& token-component {:key token-key
- :type token-key
- :selected-shapes selected-shapes
- :active-theme-tokens active-theme-tokens
- :tokens tokens
- :token-type-props token-type-props}])]]))
-
-(mf/defc json-import-button []
- (let []
- [:div
-
- [:button {:class (stl/css :download-json-button)
- :on-click #(.click (js/document.getElementById "file-input"))}
- download-icon
- "Import JSON"]]))
+ (for [{:keys [token-key token-type-props tokens]} (concat (:filled token-groups) (:empty token-groups))]
+ [:& token-component {:key token-key
+ :type token-key
+ :selected-shapes selected-shapes
+ :active-theme-tokens active-theme-tokens
+ :tokens tokens
+ :token-type-props token-type-props}])]))
(mf/defc import-export-button
{::mf/wrap-props false}
diff --git a/frontend/src/app/main/ui/workspace/tokens/sidebar.scss b/frontend/src/app/main/ui/workspace/tokens/sidebar.scss
index 81ce6b270..62010417d 100644
--- a/frontend/src/app/main/ui/workspace/tokens/sidebar.scss
+++ b/frontend/src/app/main/ui/workspace/tokens/sidebar.scss
@@ -80,25 +80,6 @@
flex-wrap: wrap;
}
-.token-pill {
- @extend .button-secondary;
- gap: $s-8;
- padding: $s-4 $s-8;
- border-radius: $br-6;
- font-size: $fs-14;
-
- &.token-pill-highlighted {
- color: var(--button-primary-foreground-color-rest);
- background: var(--button-primary-background-color-rest);
- }
-
- &.token-pill-invalid {
- background-color: var(--button-secondary-background-color-rest);
- color: var(--status-color-error-500);
- opacity: 0.8;
- }
-}
-
.section-text-icon {
font-size: $fs-12;
width: 16px;
diff --git a/frontend/src/app/main/ui/workspace/tokens/token.cljs b/frontend/src/app/main/ui/workspace/tokens/token.cljs
index 215f9ca51..3fd66ed7a 100644
--- a/frontend/src/app/main/ui/workspace/tokens/token.cljs
+++ b/frontend/src/app/main/ui/workspace/tokens/token.cljs
@@ -47,12 +47,12 @@
(= (token-identifier token) id)))
(defn token-applied?
- "Test if `token` is applied to a `shape` with at least one of the one of the given `token-attributes`."
+ "Test if `token` is applied to a `shape` with at least one of the given `token-attributes`."
[token shape token-attributes]
(some #(token-attribute-applied? token shape %) token-attributes))
(defn shapes-token-applied?
- "Test if `token` is applied to to any of `shapes` with at least one of the one of the given `token-attributes`."
+ "Test if `token` is applied to to any of `shapes` with at least one of the given `token-attributes`."
[token shapes token-attributes]
(some #(token-applied? token % token-attributes) shapes))
diff --git a/frontend/src/app/main/ui/workspace/tokens/token_pill.cljs b/frontend/src/app/main/ui/workspace/tokens/token_pill.cljs
new file mode 100644
index 000000000..d84f6fa64
--- /dev/null
+++ b/frontend/src/app/main/ui/workspace/tokens/token_pill.cljs
@@ -0,0 +1,59 @@
+(ns app.main.ui.workspace.tokens.token-pill
+ (:require-macros [app.main.style :as stl])
+ (:require
+ [app.common.types.tokens-lib :as ctob]
+ [app.main.ui.components.color-bullet :refer [color-bullet]]
+ [app.main.ui.ds.foundations.assets.icon :refer [icon*]]
+ [app.main.ui.ds.foundations.utilities.token.token-status :refer [token-status-icon*]]
+ [app.main.ui.workspace.tokens.style-dictionary :as sd]
+ [app.main.ui.workspace.tokens.token :as wtt]
+ [app.util.i18n :refer [tr]]
+ [cuerdas.core :as str]
+ [rumext.v2 :as mf]))
+
+(mf/defc token-pill
+ {::mf/wrap-props false}
+ [{:keys [on-click token theme-token full-applied on-context-menu half-applied]}]
+ (let [{:keys [name value resolved-value errors]} token
+ errors? (or (nil? theme-token) (and (seq errors) (seq (:errors theme-token))))
+
+ color (when (seq (ctob/find-token-value-references value))
+ (wtt/resolved-value-hex theme-token))
+
+ color (or color (wtt/resolved-value-hex token))
+
+ token-status-id (cond
+ half-applied
+ "token-status-partial"
+ full-applied
+ "token-status-full"
+ :else
+ "token-status-non-applied")]
+ [:button {:class (stl/css-case :token-pill true
+ :token-pill-applied full-applied
+ :token-pill-invalid errors?
+ :token-pill-invalid-applied (and full-applied errors?))
+ :type "button"
+ :title (cond
+ errors? (sd/humanize-errors token)
+ :else (->> [(str "Token: " name)
+ (tr "workspace.token.original-value" value)
+ (tr "workspace.token.resolved-value" resolved-value)]
+ (str/join "\n")))
+ :on-click on-click
+ :on-context-menu on-context-menu
+ :disabled errors?}
+ (cond
+ color
+ [:& color-bullet {:color color
+ :mini true}]
+ errors?
+ [:> icon*
+ {:id "broken-link"
+ :class (stl/css :token-pill-icon)}]
+
+ :else
+ [:> token-status-icon*
+ {:id token-status-id
+ :class (stl/css :token-pill-icon)}])
+ name]))
\ No newline at end of file
diff --git a/frontend/src/app/main/ui/workspace/tokens/token_pill.scss b/frontend/src/app/main/ui/workspace/tokens/token_pill.scss
new file mode 100644
index 000000000..138fc15b9
--- /dev/null
+++ b/frontend/src/app/main/ui/workspace/tokens/token_pill.scss
@@ -0,0 +1,106 @@
+// 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";
+@import "./common.scss";
+
+.token-pill {
+ --token-pill-background: var(--color-background-tertiary);
+ --token-pill-foreground: var(--color-foreground-secondary);
+ --token-pill-border: var(--color-background-tertiary);
+ --token-pill-outline: none;
+ --token-pill-accent: var(--color-background-quaternary);
+
+ @include use-typography("code-font");
+ border: none;
+ background: none;
+ cursor: pointer;
+ display: grid;
+ grid-template-columns: auto 1fr;
+ align-items: center;
+ gap: $s-6;
+ border: $s-1 solid var(--token-pill-border);
+ outline: $s-2 solid var(--token-pill-outline);
+ height: $s-24;
+ border-radius: $br-8;
+ padding: $s-3 $s-8;
+ color: var(--token-pill-foreground);
+ background: var(--token-pill-background);
+
+ &:hover {
+ --token-pill-background: var(--color-token-background);
+ --token-pill-foreground: var(--color-foreground-primary);
+ --token-pill-border: var(--color-token-background);
+ --token-pill-outline: none;
+ --token-pill-accent: var(--color-background-quaternary);
+ }
+
+ &:focus-visible {
+ --token-pill-outline: var(--color-background-primary);
+ --token-pill-border: var(--color-accent-primary);
+ outline-offset: -3px;
+ }
+
+ &:disabled {
+ --token-pill-background: var(--color-background-primary);
+ --token-pill-foreground: var(--color-foreground-secondary);
+ --token-pill-border: var(--color-background-tertiary);
+ --token-pill-outline: none;
+ --token-pill-accent: var(--color-background-tertiary);
+ }
+}
+
+.token-pill-applied {
+ --token-pill-background: var(--color-token-background);
+ --token-pill-foreground: var(--color-token-foreground);
+ --token-pill-border: var(--color-token-border);
+ --token-pill-accent: var(--color-token-accent);
+
+ &:hover {
+ --token-pill-background: var(--color-token-background);
+ --token-pill-foreground: var(--color-foreground-primary);
+ --token-pill-border: var(--color-token-foreground);
+ --token-pill-accent: var(--color-token-accent);
+ }
+
+ &:focus-visible {
+ --token-pill-background: var(--color-token-background);
+ --token-pill-foreground: var(--color-token-foreground);
+ --token-pill-outline: var(--color-accent-primary);
+ --token-pill-border: var(--color-token-background);
+ --token-pill-accent: var(--color-token-accent);
+ }
+
+ &:disabled {
+ --token-pill-background: var(--color-background-primary);
+ --token-pill-foreground: var(--color-token-foreground);
+ --token-pill-border: var(--color-token-accent);
+ --token-pill-outline: none;
+ --token-pill-accent: var(--color-token-accent);
+ }
+}
+
+.token-pill-invalid,
+.token-pill-invalid-applied {
+ --token-pill-background: var(--color-background-tertiary);
+ --token-pill-foreground: var(--color-foreground-error);
+ --token-pill-border: var(--color-background-tertiary);
+ --token-pill-accent: var(--color-foreground-error);
+
+ &:hover,
+ &:focus-visible,
+ &:disabled {
+ --token-pill-background: var(--color-background-tertiary);
+ --token-pill-foreground: var(--color-foreground-error);
+ --token-pill-border: var(--color-background-tertiary);
+ --token-pill-accent: var(--color-foreground-error);
+ }
+}
+
+.token-pill-icon {
+ color: var(--token-pill-accent);
+}
diff --git a/frontend/translations/en.po b/frontend/translations/en.po
index 78ce30c85..7d20c40ce 100644
--- a/frontend/translations/en.po
+++ b/frontend/translations/en.po
@@ -6240,10 +6240,6 @@ msgstr "%s sets"
msgid "workspace.token.original-value"
msgstr "Original value: "
-#: src/app/main/ui/workspace/tokens/form.cljs:193, src/app/main/ui/workspace/tokens/form.cljs:196, src/app/main/ui/workspace/tokens/sidebar.cljs:67
-msgid "workspace.token.resolved-value"
-msgstr "Resolved value: "
-
#: src/app/main/ui/workspace/tokens/modals/themes.cljs:208
msgid "workspace.token.save-theme"
msgstr "Save theme"
@@ -6573,9 +6569,9 @@ msgstr "Create new %s token"
msgid "workspace.token.edit-token"
msgstr "Edit token"
-#: src/app/main/ui/workspace/tokens/form.cljs
+#: src/app/main/ui/workspace/tokens/form.cljs, src/app/main/ui/workspace/tokens/token_pill.cljs
msgid "workspace.token.resolved-value"
-msgstr "Resolved value: "
+msgstr "Resolved value: %s"
#: src/app/main/ui/workspace/tokens/form.cljs
msgid "workspace.token.token-name"
@@ -6603,7 +6599,7 @@ msgstr "Add a description (optional)"
#: src/app/main/ui/workspace/tokens/sidebar.cljs
msgid "workspace.token.original-value"
-msgstr "Original value: "
+msgstr "Original value: %s"
#: src/app/main/ui/workspace/tokens/sidebar.cljs
msgid "workspace.token.no-themes"
diff --git a/frontend/translations/es.po b/frontend/translations/es.po
index 40929a6c9..963e4b524 100644
--- a/frontend/translations/es.po
+++ b/frontend/translations/es.po
@@ -6242,10 +6242,6 @@ msgstr "%s sets"
msgid "workspace.token.original-value"
msgstr "Valor original: "
-#: src/app/main/ui/workspace/tokens/form.cljs:193, src/app/main/ui/workspace/tokens/form.cljs:196, src/app/main/ui/workspace/tokens/sidebar.cljs:67
-msgid "workspace.token.resolved-value"
-msgstr "Valor resuelto: "
-
#: src/app/main/ui/workspace/tokens/modals/themes.cljs:208
msgid "workspace.token.save-theme"
msgstr "Guardar tema"
@@ -6573,9 +6569,9 @@ msgstr "Crear un token de %s"
msgid "workspace.token.edit-token"
msgstr "Editar token"
-#: src/app/main/ui/workspace/tokens/form.cljs
+#: src/app/main/ui/workspace/tokens/form.cljs ,src/app/main/ui/workspace/tokens/token_pill.cljs
msgid "workspace.token.resolved-value"
-msgstr "Valor resuelto: "
+msgstr "Valor resuelto: %s"
#: src/app/main/ui/workspace/tokens/form.cljs
msgid "workspace.token.token-name"
@@ -6603,7 +6599,7 @@ msgstr "Añade una Descripción (opcional)"
#: src/app/main/ui/workspace/tokens/sidebar.cljs
msgid "workspace.token.original-value"
-msgstr "Valor original: "
+msgstr "Valor original: %s"
#: src/app/main/ui/workspace/tokens/sidebar.cljs
msgid "workspace.token.no-themes"