From d9ee28229c3a2ea3c5d2098434b8ffc49d61a4e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elena=20Torr=C3=B3?= Date: Tue, 19 May 2026 11:35:30 +0200 Subject: [PATCH] :bug: Toggle token path on token rename --- .../playwright/ui/specs/tokens/tree.spec.js | 43 +++++++++++++++++++ .../data/workspace/tokens/library_edit.cljs | 18 +++++++- .../tokens/management/forms/generic_form.cljs | 36 +++++++++------- 3 files changed, 80 insertions(+), 17 deletions(-) diff --git a/frontend/playwright/ui/specs/tokens/tree.spec.js b/frontend/playwright/ui/specs/tokens/tree.spec.js index 243a539432..9f8ef72cdf 100644 --- a/frontend/playwright/ui/specs/tokens/tree.spec.js +++ b/frontend/playwright/ui/specs/tokens/tree.spec.js @@ -141,6 +141,49 @@ test.describe("Tokens - node tree", () => { await expect(darkerNodeToken).toBeVisible(); }); + test("Renaming a token into a collapsed group auto-expands that group", async ({ + page, + }) => { + const { tokensSidebar, tokensUpdateCreateModal, tokenContextMenuForToken } = + await setupTokensFileRender(page); + + // Create tokens in two separate groups + await createToken(page, "Color", "dark.base", "Value", "#000000"); + await createToken(page, "Color", "light.accent", "Value", "#ffffff"); + + const lightGroup = tokensSidebar.getByRole("button", { + name: "light", + exact: true, + }); + + // Collapse the light group so its children are hidden + await lightGroup.click(); + + const lightAccentToken = tokensSidebar.getByRole("button", { + name: "accent", + }); + await expect(lightAccentToken).not.toBeVisible(); + + // Open the edit modal for the dark.base token + const darkBaseToken = tokensSidebar.getByRole("button", { name: "base" }); + await darkBaseToken.click({ button: "right" }); + await tokenContextMenuForToken.getByText("Edit token").click(); + + await expect(tokensUpdateCreateModal).toBeVisible(); + + // Rename to move it into the collapsed light group + const nameField = tokensUpdateCreateModal.getByLabel("Name"); + await nameField.fill("light.base"); + await tokensUpdateCreateModal + .getByRole("button", { name: "Save" }) + .click(); + + // After rename, light group should be auto-expanded and both tokens visible + await expect(lightGroup).toBeVisible(); + await expect(lightAccentToken).toBeVisible(); + await expect(tokensSidebar.getByRole("button", { name: "base" })).toBeVisible(); + }); + test("User removes node and all child tokens", async ({ page }) => { const { tokensSidebar } = await setupTokensFileRender(page); diff --git a/frontend/src/app/main/data/workspace/tokens/library_edit.cljs b/frontend/src/app/main/data/workspace/tokens/library_edit.cljs index 363e796b1a..749bdd8bf4 100644 --- a/frontend/src/app/main/data/workspace/tokens/library_edit.cljs +++ b/frontend/src/app/main/data/workspace/tokens/library_edit.cljs @@ -203,7 +203,22 @@ (remove-path path paths) (add-path path paths)))))))) - +(defn toggle-nested-token-path + [token-type new-name] + (ptk/reify ::toggle-nested-token-path + ptk/UpdateEvent + (update [_ state] + (let [type-str (name token-type) + segments (str/split new-name ".") + n-groups (dec (count segments))] + (if (pos? n-groups) + (update-in state [:workspace-tokens :folded-token-paths] + (fn [paths] + (reduce (fn [ps i] + (remove-path (str type-str "." (str/join "." (take i segments))) ps)) + (or paths []) + (range 1 (inc n-groups))))) + state))))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; TOKENS Actions @@ -582,6 +597,7 @@ (pcb/set-token (ctob/get-id token-set) id token'))] + (toggle-token-path (str (name token-type) "." (:name token))) (rx/of (dch/commit-changes changes) (ev/event (-> {::ev/name "edit-token" :type token-type} (merge (meta it)))))))))) diff --git a/frontend/src/app/main/ui/workspace/tokens/management/forms/generic_form.cljs b/frontend/src/app/main/ui/workspace/tokens/management/forms/generic_form.cljs index 1606ba2eae..0835b6c238 100644 --- a/frontend/src/app/main/ui/workspace/tokens/management/forms/generic_form.cljs +++ b/frontend/src/app/main/ui/workspace/tokens/management/forms/generic_form.cljs @@ -48,7 +48,6 @@ (if (= active-tab :reference) (get value :reference) value) - value)) (mf/defc form* @@ -158,9 +157,10 @@ on-remap-token (mf/use-fn - (mf/deps token) + (mf/deps token token-type) (fn [valid-token new-name old-name description] (st/emit! + (dwtl/toggle-nested-token-path token-type new-name) (dwtl/update-token (:id token) {:name new-name :value (:value valid-token) @@ -171,9 +171,10 @@ on-rename-token (mf/use-fn - (mf/deps token) + (mf/deps token token-type) (fn [valid-token name description] (st/emit! + (dwtl/toggle-nested-token-path token-type name) (dwtl/update-token (:id token) {:name name :value (:value valid-token) @@ -210,19 +211,22 @@ (st/emit! (modal/show :tokens/remapping-confirmation {:remap-data remap-data :on-remap on-remap :on-rename on-rename})) - (st/emit! - (if is-create - (dwtl/create-token (ctob/make-token {:name name - :type token-type - :value (:value valid-token) - :description description})) - (dwtl/update-token (:id token) - {:name name - :value (:value valid-token) - :description description})) - (dwtl/open-token-type (:type token)) - (dwtp/propagate-workspace-tokens) - (modal/hide!))))) + (do + (when is-rename + (st/emit! (dwtl/toggle-nested-token-path token-type name))) + (st/emit! + (if is-create + (dwtl/create-token (ctob/make-token {:name name + :type token-type + :value (:value valid-token) + :description description})) + (dwtl/update-token (:id token) + {:name name + :value (:value valid-token) + :description description})) + (dwtl/open-token-type (:type token)) + (dwtp/propagate-workspace-tokens) + (modal/hide!)))))) ;; WORKAROUND: display validation errors in the form instead of crashing (fn [{:keys [errors]}] (let [error-messages (wte/humanize-errors errors)