Compare commits

...

1 Commits

Author SHA1 Message Date
Eva Marco
9d04606ac9 🐛 Allow detach broken token from input 2026-01-29 11:41:35 +01:00
11 changed files with 190 additions and 40 deletions

View File

@@ -48,6 +48,12 @@
applied-tokens)
(into {}))))
(defn remove-attribute-for-detached-token
"Removes applied tokens when token-id is nil for the given `attributes` set from `applied-tokens`."
[attributes applied-tokens]
(prn applied-tokens)
(apply dissoc applied-tokens attributes))
(defn token-attribute-applied?
"Test if `token` is applied to a `shape` on single `token-attribute`."
[token shape token-attribute]

View File

@@ -831,15 +831,102 @@ test.describe("Tokens: Apply token", () => {
});
await detachButton.click();
await expect(marginPillXL).not.toBeVisible();
const horizontalMarginInput = layoutItemSectionSidebar.getByText('Horizontal marginOpen token');
const horizontalMarginInput = layoutItemSectionSidebar.getByText(
"Horizontal marginOpen token",
);
await expect(horizontalMarginInput).toBeVisible();
const tokenDropdown = horizontalMarginInput.getByRole('button', { name: 'Open token list' });
const tokenDropdown = horizontalMarginInput.getByRole("button", {
name: "Open token list",
});
await tokenDropdown.click();
await expect(dimensionTokenOptionXl).toBeVisible();
await dimensionTokenOptionXl.click();
await expect(marginPillXL).toBeVisible();
});
});
test.describe("Tokens: Detach token", () => {
test("User applies border-radius token to a shape from sidebar", async ({
page,
}) => {
const { workspacePage, tokensSidebar, tokenContextMenuForToken } =
await setupTokensFile(page);
await page.getByRole("tab", { name: "Layers" }).click();
await workspacePage.layers.getByTestId("layer-row").nth(1).click();
// Open tokens sections on left sidebar
const tokensTabButton = page.getByRole("tab", { name: "Tokens" });
await tokensTabButton.click();
// Unfold border radius tokens
await page.getByRole("button", { name: "Border Radius 3" }).click();
await expect(
tokensSidebar.getByRole("button", { name: "borderRadius" }),
).toBeVisible();
await tokensSidebar.getByRole("button", { name: "borderRadius" }).click();
await expect(
tokensSidebar.getByRole("button", { name: "borderRadius.sm" }),
).toBeVisible();
// Apply border radius token from token panels
await tokensSidebar
.getByRole("button", { name: "borderRadius.sm" })
.click();
// Check if border radius sections is visible on right sidebar
const borderRadiusSection = page.getByRole("region", {
name: "border-radius-section",
});
await expect(borderRadiusSection).toBeVisible();
// Check if token pill is visible on design tab on right sidebar
const brTokenPillSM = borderRadiusSection.getByRole("button", {
name: "borderRadius.sm",
});
await expect(brTokenPillSM).toBeVisible();
await brTokenPillSM.click();
// Rename token
await tokensSidebar
.getByRole("button", { name: "borderRadius.sm" })
.click({ button: "right" });
await expect(page.getByText("Edit token")).toBeVisible();
await page.getByText("Edit token").click();
const editModal = page.getByTestId("token-update-create-modal");
await expect(editModal).toBeVisible();
await expect(
editModal.getByRole("textbox", { name: "Name" }),
).toBeVisible();
await editModal
.getByRole("textbox", { name: "Name" })
.fill("BorderRadius.smBis");
const submitButton = editModal.getByRole("button", { name: "Save" });
await expect(submitButton).toBeEnabled();
await submitButton.click();
await expect(page.getByText("Don't remap")).toBeVisible();
await page.getByText("Don't remap").click();
const brokenPill = borderRadiusSection.getByRole("button", {
name: "This token is not in any",
});
await expect(brokenPill).toBeVisible();
// Detach broken token
const detachButton = borderRadiusSection.getByRole("button", {
name: "Detach token",
});
await detachButton.click();
await expect(brokenPill).not.toBeVisible();
//De-select and select shape again to double check token is detached
await page.getByRole("tab", { name: "Layers" }).click();
await workspacePage.layers.getByTestId("layer-row").nth(0).click();
await workspacePage.layers.getByTestId("layer-row").nth(1).click();
await expect(brokenPill).not.toBeVisible();
});
});

View File

@@ -710,6 +710,23 @@
(fn [shape]
(update shape :applied-tokens remove-token))))))))
(defn detach-token
"Removes `attributes` when token-id is nil.
Doesn't update shape attributes."
[{:keys [attributes shape-ids] :as _props}]
(ptk/reify ::unapply-token
ptk/WatchEvent
(watch [_ _ _]
(prn "entro en el detach")
(prn attributes)
(rx/of
(let [remove-token #(when % (cft/remove-attribute-for-detached-token attributes %))]
(dwsh/update-shapes
shape-ids
(fn [shape]
(update shape :applied-tokens remove-token))))))))
(defn toggle-token
[{:keys [token attrs shape-ids expand-with-children]}]
(ptk/reify ::on-toggle-token

View File

@@ -119,9 +119,12 @@
(mf/use-fn
(mf/deps ids)
(fn [token attr]
(st/emit! (dwta/unapply-token {:token (first token)
:attributes #{attr}
:shape-ids ids}))))
(if (seq token)
(st/emit! (dwta/unapply-token {:token (first token)
:attributes #{attr}
:shape-ids ids}))
(st/emit! (dwta/detach-token {:attributes #{attr}
:shape-ids ids})))))
on-detach-all
(mf/use-fn

View File

@@ -166,9 +166,16 @@
(d/without-nils))]
(mf/set-ref-val! prev-colors-ref
(conj prev-colors color))
(st/emit! (dwta/unapply-token {:attributes attr
:token token
:shape-ids [(:shape-id op)]})))))))
(prn token)
(if (seq token)
(st/emit! (dwta/unapply-token {:token (first token)
:attributes attr
:shape-ids [(:shape-id op)]}))
(st/emit! (dwta/detach-token {:attributes attr
:shape-ids [(:shape-id op)]})))
#_(st/emit! (dwta/unapply-token {:attributes attr
:token token
:shape-ids [(:shape-id op)]})))))))
select-only
(mf/use-fn

View File

@@ -74,7 +74,6 @@
render-wasm? (feat/use-feature "render-wasm/v1")
^boolean
multiple? (= :multiple fills)
@@ -184,9 +183,13 @@
(mf/use-fn
(mf/deps ids)
(fn [token]
(st/emit! (dwta/unapply-token {:attributes #{:fill}
:token token
:shape-ids ids}))))]
(prn "on-detach-token" token)
(if (seq token)
(st/emit! (dwta/unapply-token {:token (first token)
:attributes #{:fill}
:shape-ids ids}))
(st/emit! (dwta/detach-token {:attributes #{:fill}
:shape-ids ids})))))]
(mf/with-layout-effect [hide-on-export]
(when-let [checkbox (mf/ref-val checkbox-ref)]

View File

@@ -105,9 +105,12 @@
(mf/use-fn
(mf/deps ids)
(fn [token attr]
(st/emit! (dwta/unapply-token {:token (first token)
:attributes #{attr}
:shape-ids ids}))))
(if (seq token)
(st/emit! (dwta/unapply-token {:token (first token)
:attributes #{attr}
:shape-ids ids}))
(st/emit! (dwta/detach-token {:attributes #{attr}
:shape-ids ids})))))
current-blend-mode (or (get values :blend-mode) :normal)
current-opacity (opacity->string (:opacity values))

View File

@@ -380,9 +380,12 @@
(mf/use-fn
(mf/deps ids)
(fn [token attr]
(st/emit! (dwta/unapply-token {:token (first token)
:attributes #{attr}
:shape-ids ids}))))
(if (seq token)
(st/emit! (dwta/unapply-token {:token (first token)
:attributes #{attr}
:shape-ids ids}))
(st/emit! (dwta/detach-token {:attributes #{attr}
:shape-ids ids})))))
on-focus
(mf/use-fn
@@ -498,9 +501,12 @@
(mf/use-fn
(mf/deps ids)
(fn [token attr]
(st/emit! (dwta/unapply-token {:token (first token)
:attributes #{attr}
:shape-ids ids}))))
(if (seq token)
(st/emit! (dwta/unapply-token {:token (first token)
:attributes #{attr}
:shape-ids ids}))
(st/emit! (dwta/detach-token {:attributes #{attr}
:shape-ids ids})))))
on-p1-change
(mf/use-fn (mf/deps on-change') #(on-change' % :p1))
@@ -725,9 +731,12 @@
(mf/use-fn
(mf/deps ids)
(fn [token attr]
(st/emit! (dwta/unapply-token {:token (first token)
:attributes #{attr}
:shape-ids ids}))))
(if (seq token)
(st/emit! (dwta/unapply-token {:token (first token)
:attributes #{attr}
:shape-ids ids}))
(st/emit! (dwta/detach-token {:attributes #{attr}
:shape-ids ids})))))
on-row-gap-change
(mf/use-fn (mf/deps on-change') #(on-change' %1 %2 :row-gap))

View File

@@ -145,9 +145,12 @@
(mf/use-fn
(mf/deps ids)
(fn [token attr]
(st/emit! (dwta/unapply-token {:token (first token)
:attributes #{attr}
:shape-ids ids}))))
(if (seq token)
(st/emit! (dwta/unapply-token {:token (first token)
:attributes #{attr}
:shape-ids ids}))
(st/emit! (dwta/detach-token {:attributes #{attr}
:shape-ids ids})))))
on-detach-horizontal
(mf/use-fn
@@ -266,9 +269,12 @@
(mf/use-fn
(mf/deps ids)
(fn [token attr]
(st/emit! (dwta/unapply-token {:token (first token)
:attributes #{attr}
:shape-ids ids}))))
(if (seq token)
(st/emit! (dwta/unapply-token {:token (first token)
:attributes #{attr}
:shape-ids ids}))
(st/emit! (dwta/detach-token {:attributes #{attr}
:shape-ids ids})))))
on-focus
(mf/use-fn
@@ -592,9 +598,12 @@
(mf/use-fn
(mf/deps ids)
(fn [token attr]
(st/emit! (dwta/unapply-token {:token (first token)
:attributes #{attr}
:shape-ids ids}))))
(if (seq token)
(st/emit! (dwta/unapply-token {:token (first token)
:attributes #{attr}
:shape-ids ids}))
(st/emit! (dwta/detach-token {:attributes #{attr}
:shape-ids ids})))))
on-size-change
(mf/use-fn

View File

@@ -348,9 +348,12 @@
(mf/use-fn
(mf/deps ids)
(fn [token attr]
(st/emit! (dwta/unapply-token {:token (first token)
:attributes #{attr}
:shape-ids ids}))))
(if (seq token)
(st/emit! (dwta/unapply-token {:token (first token)
:attributes #{attr}
:shape-ids ids}))
(st/emit! (dwta/detach-token {:attributes #{attr}
:shape-ids ids})))))
;; CLIP CONTENT AND SHOW IN VIEWER
on-change-clip-content

View File

@@ -172,9 +172,12 @@
(mf/use-fn
(mf/deps ids)
(fn [token attrs]
(st/emit! (dwta/unapply-token {:attributes attrs
:token token
:shape-ids ids}))))]
(if (seq token)
(st/emit! (dwta/unapply-token {:token (first token)
:attributes attrs
:shape-ids ids}))
(st/emit! (dwta/detach-token {:attributes attrs
:shape-ids ids})))))]
[:section {:class (stl/css :stroke-section)
:aria-label "stroke-section"}