🎉 Add typography token row to multiselected texts (#9128)

* 🐛 Fix text multiselection messages

* ♻️ Add tooltip to typography tooltip

* ♻️ Improve copy and add detach buttons
This commit is contained in:
Eva Marco 2026-05-19 09:47:04 +02:00 committed by GitHub
parent 595ec599c6
commit e854309049
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 164 additions and 45 deletions

View File

@ -250,14 +250,14 @@ test("Multiselection of text and typographies", async ({ page }) => {
await expect(textSection).toBeVisible();
await expect(
textSection.getByText("Multiple typographies"),
textSection.getByText("Mixed assets"),
).not.toBeVisible();
// Select two plain text layer with different font family
await plainTextLayerTwo.click({ modifiers: ["Control"] });
await expect(textSection).toBeVisible();
await expect(
textSection.getByTitle("Font family").getByText("--"),
textSection.getByTitle("Font family").getByText("Mixed Font Families"),
).toBeVisible();
// Select typography text layer
@ -268,7 +268,7 @@ test("Multiselection of text and typographies", async ({ page }) => {
// Select two typography text layer with different typography
await typographyTextLayerTwo.click({ modifiers: ["Control"] });
await expect(textSection).toBeVisible();
await expect(textSection.getByText("Multiple typographies")).toBeVisible();
await expect(textSection.getByText("Mixed assets")).toBeVisible();
// Select token typography text layer
// TODO: CHANGE WHEN TOKEN TYPOGRAPHY ROW IS READY
@ -281,32 +281,32 @@ test("Multiselection of text and typographies", async ({ page }) => {
await tokenTypographyTextLayerTwo.click({ modifiers: ["Control"] });
await expect(textSection).toBeVisible();
await expect(
textSection.getByTitle("Font family").getByText("--"),
textSection.getByTitle("Font family").getByText("Mixed Font Families"),
).toBeVisible();
//Select plain text layer and typography text layer together
await plainTextLayer.click();
await typographyTextLayerOne.click({ modifiers: ["Control"] });
await expect(textSection).toBeVisible();
await expect(textSection.getByText("Multiple typographies")).toBeVisible();
await expect(textSection.getByText("Mixed assets")).toBeVisible();
//Select plain text layer and typography text layer together on reverse order
await typographyTextLayerOne.click();
await plainTextLayer.click({ modifiers: ["Control"] });
await expect(textSection).toBeVisible();
await expect(textSection.getByText("Multiple typographies")).toBeVisible();
await expect(textSection.getByText("Mixed assets")).toBeVisible();
//Selen token typography text layer and typography text layer together
await tokenTypographyTextLayerOne.click();
await typographyTextLayerOne.click({ modifiers: ["Control"] });
await expect(textSection).toBeVisible();
await expect(textSection.getByText("Multiple typographies")).toBeVisible();
await expect(textSection.getByText("Mixed assets")).toBeVisible();
//Select token typography text layer and typography text layer together on reverse order
await typographyTextLayerOne.click();
await tokenTypographyTextLayerOne.click({ modifiers: ["Control"] });
await expect(textSection).toBeVisible();
await expect(textSection.getByText("Multiple typographies")).toBeVisible();
await expect(textSection.getByText("Mixed assets")).toBeVisible();
// Select rectangle and elipse together
await rectangleLayer.click();

View File

@ -777,6 +777,19 @@
(fn [shape]
(update shape :applied-tokens remove-token))))))))
(defn unapply-multiple-tokens
"Removes `attributes` for `shape-ids` without knowing the token, used when a token is deleted."
[{:keys [attributes shape-ids] :as _props}]
(ptk/reify ::unapply-multiple-tokens
ptk/WatchEvent
(watch [_ _ _]
(rx/of
(dwsh/update-shapes
shape-ids
(fn [shape]
(update shape :applied-tokens #(when % (apply dissoc % attributes)))))))))
(defn toggle-token
[{:keys [token attrs shape-ids expand-with-children]}]

View File

@ -60,8 +60,10 @@
id (d/nilv id internal-id)
element-ref (mf/use-ref nil)
tooltip-content (if (map? resolved)
(mf/html [:> resolved-value-tooltip* {:token-name name
:resolved-value resolved}])
(mf/html
[:> resolved-value-tooltip*
{:token-name name
:resolved-value resolved}])
name)]
[:li {:value id
:class (stl/css-case :token-option true

View File

@ -294,7 +294,7 @@
sorted-tokens (sort-combined-tokens filtered-combined)]
(if (seq combined-tokens)
[:div {:class (stl/css :color-tokens-section)}
[:> input* {:placeholder "Search by token name"
[:> input* {:placeholder (tr "workspace.tokens.search-by-token")
:icon i/search
:max-length max-input-length
:variant "comfortable"

View File

@ -292,7 +292,7 @@
(csu/get-token-dropdown-options typography-tokens nil))
selected-token-id*
(mf/use-state #(when current-token-name
(mf/use-state #(when (and (not= :multiple current-token-name) current-token-name)
(:id (get-option-by-name dropdown-options current-token-name))))
selected-token-id (deref selected-token-id*)
@ -411,11 +411,19 @@
detach-token
(mf/use-fn
(mf/deps ids)
(fn [token-name]
(st/emit! (dwta/unapply-token {:token-name token-name
:attributes #{:typography}
:shape-ids ids}))))
handle-detach-all-tokens
(mf/use-fn
(mf/deps ids)
(fn []
(st/emit! (dwta/unapply-multiple-tokens {:attributes #{:typography}
:shape-ids ids}))))
expand-stream
(mf/with-memo []
(->> st/stream (rx/filter (ptk/type? :expand-text-more-options))))
@ -445,7 +453,7 @@
(mf/with-effect [applied-token-name dropdown-options]
(reset! selected-token-id*
(when applied-token-name
(when (and (not= :multiple applied-token-name) applied-token-name)
(:id (get-option-by-name dropdown-options applied-token-name)))))
(mf/with-effect [token-dropdown-open?]
@ -477,11 +485,36 @@
(when main-menu-open?
[:div {:class (stl/css :element-content)}
(cond
(and token-typography-row-enabled? (= :multiple current-token-name) (= typography-id :multiple))
[:div {:class (stl/css :multiple-typography)}
[:span {:class (stl/css :multiple-text)}
(tr "workspace.libraries.text.mixed-tokens-and-assets")]]
(and token-typography-row-enabled? (= :multiple current-token-name))
[:div {:class (stl/css :multiple-typography)}
[:span {:class (stl/css :multiple-text)}
(tr "workspace.libraries.text.mixed-tokens")]
[:> icon-button* {:variant "ghost"
:aria-label (tr "workspace.libraries.text.multiple-token-tooltip")
:tooltip-placement "top-left"
:on-click handle-detach-all-tokens
:icon i/detach}]]
(and token-typography-row-enabled? current-token-name)
[:> token-typography-row* {:token-name current-token-name
:detach-token detach-token
:active-tokens (resolve-delay typography-tokens)}]
(= typography-id :multiple)
[:div {:class (stl/css :multiple-typography)}
[:span {:class (stl/css :multiple-text)}
(tr "workspace.libraries.text.mixed-typography")]
[:> icon-button* {:variant "ghost"
:aria-label (tr "workspace.libraries.text.multiple-assets-tooltip")
:on-click handle-detach-typography
:tooltip-placement "top-left"
:icon i/detach}]]
typography
[:& typography-entry {:file-id typography-file-id
:typography typography
@ -489,13 +522,7 @@
:on-detach handle-detach-typography
:on-change handle-change-typography}]
(= typography-id :multiple)
[:div {:class (stl/css :multiple-typography)}
[:span {:class (stl/css :multiple-text)} (tr "workspace.libraries.text.multiple-typography")]
[:> icon-button* {:variant "ghost"
:aria-label (tr "workspace.libraries.text.multiple-typography-tooltip")
:on-click handle-detach-typography
:icon i/detach}]]
:else
[:> text-options* common-props])
@ -521,4 +548,5 @@
:options (resolve-delay dropdown-options)
:selected selected-token-id
:align "right"
:placeholder (tr "workspace.tokens.search-by-token")
:ref set-option-ref}])]))

View File

@ -4,11 +4,18 @@
//
// Copyright (c) KALEIDOS INC
@use "refactor/common-refactor.scss" as deprecated;
@use "../../../sidebar/common/sidebar.scss" as sidebar;
@use "ds/typography.scss" as t;
@use "ds/_utils.scss" as *;
@use "ds/_sizes.scss" as *;
@use "ds/_borders.scss" as *;
@use "ds/spacing.scss" as *;
@use "ds/mixins.scss" as *;
.element-set {
@include sidebar.option-grid-structure;
position: relative;
}
.element-title {
@ -16,37 +23,37 @@
}
.element-content {
@include deprecated.flex-column;
display: flex;
flex-direction: column;
gap: var(--sp-xs);
grid-column: span 8;
margin-top: deprecated.$s-4;
margin-block-start: var(--sp-xs);
}
.multiple-typography {
@extend %mixed-bar;
@include t.use-typography("body-small");
display: flex;
align-items: center;
flex-grow: 1;
border-radius: $br-8;
block-size: $sz-32;
padding-block: var(--sp-s);
padding-inline: var(--sp-s) 0;
background-color: var(--color-background-tertiary);
color: var(--color-foreground-primary);
}
.multiple-text {
@include deprecated.body-small-typography;
@include t.use-typography("body-small");
flex-grow: 1;
color: var(--input-foreground-color-active);
}
.multiple-typography-button {
@extend %button-tertiary;
height: deprecated.$s-32;
width: deprecated.$s-28;
svg {
@extend %button-icon;
}
color: var(--color-foreground-secondary);
}
.text-align-options {
display: flex;
gap: deprecated.$s-4;
gap: var(--sp-xs);
}
.align-options,
@ -54,10 +61,10 @@
.vertical-align-options,
.grow-options,
.text-decoration-options {
height: deprecated.$s-32;
block-size: $sz-32;
}
.text-decoration-options {
display: flex;
gap: deprecated.$s-4;
gap: var(--sp-xs);
}

View File

@ -315,7 +315,12 @@
:on-click #(reset! open-selector? true)}
(cond
(or (= :multiple font-id) (= "mixed" font-id))
"--"
[:*
[:span {:class (stl/css :font-option-name :font-family-mixed)}
(tr "inspect.attributes.typography.mixed-font-family")]
[:> icon* {:icon-id i/arrow-down
:class (stl/css :dropdown-icon)
:size "s"}]]
(some? font)
[:*

View File

@ -51,6 +51,10 @@
visibility: var(--actions-visibility);
}
.font-family-mixed {
color: var(--color-foreground-secondary);
}
.typography-selection-wrapper {
display: grid;
grid-template-columns: $sz-24 auto 1fr;

View File

@ -274,7 +274,7 @@
(merge-attrs shape-attrs)
(merge-attrs content-attrs))
new-token-acc (merge-token-values token-acc content-attrs applied-tokens)]
new-token-acc (merge-token-values token-acc editable-attrs applied-tokens)]
[(conj ids id)
new-values
new-token-acc])

View File

@ -2015,6 +2015,10 @@ msgstr "Typography"
msgid "inspect.attributes.typography.font-family"
msgstr "Font Family"
#: src/app/main/ui/workspace/sidebar/options/menus/typography.cljs:308
msgid "inspect.attributes.typography.mixed-font-family"
msgstr "Mixed Font Families"
#: src/app/main/ui/workspace/sidebar/options/menus/typography.cljs:326, src/app/main/ui/workspace/sidebar/options/menus/typography.cljs:332
msgid "inspect.attributes.typography.font-size"
msgstr "Font Size"
@ -6347,10 +6351,34 @@ msgstr "Connect library"
msgid "workspace.libraries.text.multiple-typography"
msgstr "Multiple typographies"
#: src/app/main/ui/workspace/sidebar/options/menus/text.cljs:332
msgid "workspace.libraries.text.mixed-typography"
msgstr "Mixed assets"
#: src/app/main/ui/workspace/sidebar/options/menus/text.cljs:332
msgid "workspace.libraries.text.mixed-tokens"
msgstr "Mixed tokens"
#: src/app/main/ui/workspace/sidebar/options/menus/text.cljs:332
msgid "workspace.libraries.text.mixed-tokens-and-assets"
msgstr "Mixed assets and tokens"
#: src/app/main/ui/workspace/sidebar/options/menus/text.cljs:335
msgid "workspace.libraries.text.multiple-typography-tooltip"
msgstr "Unlink all typographies"
#: src/app/main/ui/workspace/sidebar/options/menus/text.cljs:335
msgid "workspace.libraries.text.multiple-assets-tooltip"
msgstr "Unlink all assets"
#: src/app/main/ui/workspace/sidebar/options/menus/text.cljs:335
msgid "workspace.libraries.text.multiple-token-tooltip"
msgstr "Detach all tokens"
#: src/app/main/ui/workspace/sidebar/options/menus/text.cljs:335
msgid "workspace.libraries.text.multiple-token-and-asset-tooltip"
msgstr "Detach all tokens & unlink all typographies"
#: src/app/main/ui/workspace/libraries.cljs:103, src/app/main/ui/workspace/libraries.cljs:130
msgid "workspace.libraries.typography"
msgid_plural "workspace.libraries.typography"
@ -8960,6 +8988,10 @@ msgstr "Duplicate Tokens Group"
msgid "workspace.tokens.rename-group-name-hint"
msgstr "Your tokens will automatically be renamed to %s.(suffix).(tokenName)"
#: src/app/main/ui/workspace/sidebar/options/menus/text.cljs, src/app/main/ui/workspace/colorpicker/color_tokens.cljs
msgid "workspace.tokens.search-by-token"
msgstr "Search by token name"
#: src/app/main/ui/workspace/sidebar.cljs:159, src/app/main/ui/workspace/sidebar.cljs:166
msgid "workspace.toolbar.assets"
msgstr "Assets"

View File

@ -1958,6 +1958,10 @@ msgstr "Tipografía"
msgid "inspect.attributes.typography.font-family"
msgstr "Familia tipográfica"
#: src/app/main/ui/workspace/sidebar/options/menus/typography.cljs:308
msgid "inspect.attributes.typography.mixed-font-family"
msgstr "Varias Familias tipográficas"
#: src/app/main/ui/workspace/sidebar/options/menus/typography.cljs:326, src/app/main/ui/workspace/sidebar/options/menus/typography.cljs:332
msgid "inspect.attributes.typography.font-size"
msgstr "Tamaño de fuente"
@ -6216,13 +6220,33 @@ msgid "workspace.libraries.shared-library-btn"
msgstr "Conectar biblioteca"
#: src/app/main/ui/workspace/sidebar/options/menus/text.cljs:332
msgid "workspace.libraries.text.multiple-typography"
msgstr "Varias tipografías"
msgid "workspace.libraries.text.mixed-typography"
msgstr "Varios recursos"
#: src/app/main/ui/workspace/sidebar/options/menus/text.cljs:332
msgid "workspace.libraries.text.mixed-tokens"
msgstr "Varios tokens"
#: src/app/main/ui/workspace/sidebar/options/menus/text.cljs:332
msgid "workspace.libraries.text.mixed-tokens-and-assets"
msgstr "Varios tokens y recursos"
#: src/app/main/ui/workspace/sidebar/options/menus/text.cljs:335
msgid "workspace.libraries.text.multiple-typography-tooltip"
msgstr "Desvincular todas las tipografías"
#: src/app/main/ui/workspace/sidebar/options/menus/text.cljs:335
msgid "workspace.libraries.text.multiple-assets-tooltip"
msgstr "Desvincular todos los recursos"
#: src/app/main/ui/workspace/sidebar/options/menus/text.cljs:335
msgid "workspace.libraries.text.multiple-token-tooltip"
msgstr "Desvincular todos los tokens"
#: src/app/main/ui/workspace/sidebar/options/menus/text.cljs:335
msgid "workspace.libraries.text.multiple-token-and-asset-tooltip"
msgstr "Desvincular todos los tokens y recursos"
#: src/app/main/ui/workspace/libraries.cljs:103, src/app/main/ui/workspace/libraries.cljs:130
msgid "workspace.libraries.typography"
msgid_plural "workspace.libraries.typography"
@ -8674,6 +8698,10 @@ msgstr "Duplicar grupo de tokens"
msgid "workspace.tokens.rename-group-name-hint"
msgstr "Tus tokens serán automáticamente renombrados a %s.(sufijo).(token)"
#: src/app/main/ui/workspace/sidebar/options/menus/text.cljs, src/app/main/ui/workspace/colorpicker/color_tokens.cljs
msgid "workspace.tokens.search-by-token"
msgstr "Buscar por el nombre del token"
#: src/app/main/ui/workspace/sidebar.cljs:159, src/app/main/ui/workspace/sidebar.cljs:166
msgid "workspace.toolbar.assets"
msgstr "Recursos"