diff --git a/frontend/playwright/data/workspace/get-file-tokens.json b/frontend/playwright/data/workspace/get-file-tokens.json index 4f2f2cdad..ba15a126a 100644 --- a/frontend/playwright/data/workspace/get-file-tokens.json +++ b/frontend/playwright/data/workspace/get-file-tokens.json @@ -1371,271 +1371,279 @@ } ], [ - "S-light", + "G-LightDark", { - "~#penpot/token-set": { - "~:name": "light", - "~:description": null, - "~:modified-at": "~m1737542498290", - "~:tokens": { - "~#ordered-map": [ - [ - "accent.default", - { - "~#penpot/token": { - "~:name": "accent.default", - "~:type": "~:color", - "~:value": "{colors.indigo.400}", - "~:description": null, - "~:modified-at": "~m1737542498290" - } + "~#ordered-map": [ + [ + "S-light", + { + "~#penpot/token-set": { + "~:name": "LightDark/light", + "~:description": null, + "~:modified-at": "~m1737542498290", + "~:tokens": { + "~#ordered-map": [ + [ + "accent.default", + { + "~#penpot/token": { + "~:name": "accent.default", + "~:type": "~:color", + "~:value": "{colors.indigo.400}", + "~:description": null, + "~:modified-at": "~m1737542498290" + } + } + ], + [ + "bg.muted", + { + "~#penpot/token": { + "~:name": "bg.muted", + "~:type": "~:color", + "~:value": "{colors.gray.100}", + "~:description": null, + "~:modified-at": "~m1737542498290" + } + } + ], + [ + "bg.subtle", + { + "~#penpot/token": { + "~:name": "bg.subtle", + "~:type": "~:color", + "~:value": "{colors.gray.200}", + "~:description": null, + "~:modified-at": "~m1737542498290" + } + } + ], + [ + "accent.bg", + { + "~#penpot/token": { + "~:name": "accent.bg", + "~:type": "~:color", + "~:value": "{colors.indigo.200}", + "~:description": null, + "~:modified-at": "~m1737542498290" + } + } + ], + [ + "accent.onAccent", + { + "~#penpot/token": { + "~:name": "accent.onAccent", + "~:type": "~:color", + "~:value": "{colors.white}", + "~:description": null, + "~:modified-at": "~m1737542498290" + } + } + ], + [ + "shadows.default", + { + "~#penpot/token": { + "~:name": "shadows.default", + "~:type": "~:color", + "~:value": "{colors.gray.900}", + "~:description": null, + "~:modified-at": "~m1737542498290" + } + } + ], + [ + "fg.muted", + { + "~#penpot/token": { + "~:name": "fg.muted", + "~:type": "~:color", + "~:value": "{colors.gray.700}", + "~:description": null, + "~:modified-at": "~m1737542498289" + } + } + ], + [ + "fg.default", + { + "~#penpot/token": { + "~:name": "fg.default", + "~:type": "~:color", + "~:value": "{colors.black}", + "~:description": null, + "~:modified-at": "~m1737542498289" + } + } + ], + [ + "fg.subtle", + { + "~#penpot/token": { + "~:name": "fg.subtle", + "~:type": "~:color", + "~:value": "{colors.gray.500}", + "~:description": null, + "~:modified-at": "~m1737542498290" + } + } + ], + [ + "bg.default", + { + "~#penpot/token": { + "~:name": "bg.default", + "~:type": "~:color", + "~:value": "{colors.white}", + "~:description": null, + "~:modified-at": "~m1737542498290" + } + } + ] + ] } - ], - [ - "bg.muted", - { - "~#penpot/token": { - "~:name": "bg.muted", - "~:type": "~:color", - "~:value": "{colors.gray.100}", - "~:description": null, - "~:modified-at": "~m1737542498290" - } + } + } + ], + + [ + "S-dark", + { + "~#penpot/token-set": { + "~:name": "LightDark/dark", + "~:description": null, + "~:modified-at": "~m1737542498291", + "~:tokens": { + "~#ordered-map": [ + [ + "accent.default", + { + "~#penpot/token": { + "~:name": "accent.default", + "~:type": "~:color", + "~:value": "{colors.indigo.600}", + "~:description": null, + "~:modified-at": "~m1737542498291" + } + } + ], + [ + "bg.muted", + { + "~#penpot/token": { + "~:name": "bg.muted", + "~:type": "~:color", + "~:value": "{colors.gray.700}", + "~:description": null, + "~:modified-at": "~m1737542498291" + } + } + ], + [ + "bg.subtle", + { + "~#penpot/token": { + "~:name": "bg.subtle", + "~:type": "~:color", + "~:value": "{colors.gray.600}", + "~:description": null, + "~:modified-at": "~m1737542498291" + } + } + ], + [ + "accent.bg", + { + "~#penpot/token": { + "~:name": "accent.bg", + "~:type": "~:color", + "~:value": "{colors.indigo.800}", + "~:description": null, + "~:modified-at": "~m1737542498291" + } + } + ], + [ + "accent.onAccent", + { + "~#penpot/token": { + "~:name": "accent.onAccent", + "~:type": "~:color", + "~:value": "{colors.white}", + "~:description": null, + "~:modified-at": "~m1737542498291" + } + } + ], + [ + "shadows.default", + { + "~#penpot/token": { + "~:name": "shadows.default", + "~:type": "~:color", + "~:value": "rgba({colors.black}, 0.3)", + "~:description": null, + "~:modified-at": "~m1737542498291" + } + } + ], + [ + "fg.muted", + { + "~#penpot/token": { + "~:name": "fg.muted", + "~:type": "~:color", + "~:value": "{colors.gray.300}", + "~:description": null, + "~:modified-at": "~m1737542498291" + } + } + ], + [ + "fg.default", + { + "~#penpot/token": { + "~:name": "fg.default", + "~:type": "~:color", + "~:value": "{colors.white}", + "~:description": null, + "~:modified-at": "~m1737542498291" + } + } + ], + [ + "fg.subtle", + { + "~#penpot/token": { + "~:name": "fg.subtle", + "~:type": "~:color", + "~:value": "{colors.gray.500}", + "~:description": null, + "~:modified-at": "~m1737542498291" + } + } + ], + [ + "bg.default", + { + "~#penpot/token": { + "~:name": "bg.default", + "~:type": "~:color", + "~:value": "{colors.gray.900}", + "~:description": null, + "~:modified-at": "~m1737542498291" + } + } + ] + ] } - ], - [ - "bg.subtle", - { - "~#penpot/token": { - "~:name": "bg.subtle", - "~:type": "~:color", - "~:value": "{colors.gray.200}", - "~:description": null, - "~:modified-at": "~m1737542498290" - } - } - ], - [ - "accent.bg", - { - "~#penpot/token": { - "~:name": "accent.bg", - "~:type": "~:color", - "~:value": "{colors.indigo.200}", - "~:description": null, - "~:modified-at": "~m1737542498290" - } - } - ], - [ - "accent.onAccent", - { - "~#penpot/token": { - "~:name": "accent.onAccent", - "~:type": "~:color", - "~:value": "{colors.white}", - "~:description": null, - "~:modified-at": "~m1737542498290" - } - } - ], - [ - "shadows.default", - { - "~#penpot/token": { - "~:name": "shadows.default", - "~:type": "~:color", - "~:value": "{colors.gray.900}", - "~:description": null, - "~:modified-at": "~m1737542498290" - } - } - ], - [ - "fg.muted", - { - "~#penpot/token": { - "~:name": "fg.muted", - "~:type": "~:color", - "~:value": "{colors.gray.700}", - "~:description": null, - "~:modified-at": "~m1737542498289" - } - } - ], - [ - "fg.default", - { - "~#penpot/token": { - "~:name": "fg.default", - "~:type": "~:color", - "~:value": "{colors.black}", - "~:description": null, - "~:modified-at": "~m1737542498289" - } - } - ], - [ - "fg.subtle", - { - "~#penpot/token": { - "~:name": "fg.subtle", - "~:type": "~:color", - "~:value": "{colors.gray.500}", - "~:description": null, - "~:modified-at": "~m1737542498290" - } - } - ], - [ - "bg.default", - { - "~#penpot/token": { - "~:name": "bg.default", - "~:type": "~:color", - "~:value": "{colors.white}", - "~:description": null, - "~:modified-at": "~m1737542498290" - } - } - ] - ] - } - } - } - ], - [ - "S-dark", - { - "~#penpot/token-set": { - "~:name": "dark", - "~:description": null, - "~:modified-at": "~m1737542498291", - "~:tokens": { - "~#ordered-map": [ - [ - "accent.default", - { - "~#penpot/token": { - "~:name": "accent.default", - "~:type": "~:color", - "~:value": "{colors.indigo.600}", - "~:description": null, - "~:modified-at": "~m1737542498291" - } - } - ], - [ - "bg.muted", - { - "~#penpot/token": { - "~:name": "bg.muted", - "~:type": "~:color", - "~:value": "{colors.gray.700}", - "~:description": null, - "~:modified-at": "~m1737542498291" - } - } - ], - [ - "bg.subtle", - { - "~#penpot/token": { - "~:name": "bg.subtle", - "~:type": "~:color", - "~:value": "{colors.gray.600}", - "~:description": null, - "~:modified-at": "~m1737542498291" - } - } - ], - [ - "accent.bg", - { - "~#penpot/token": { - "~:name": "accent.bg", - "~:type": "~:color", - "~:value": "{colors.indigo.800}", - "~:description": null, - "~:modified-at": "~m1737542498291" - } - } - ], - [ - "accent.onAccent", - { - "~#penpot/token": { - "~:name": "accent.onAccent", - "~:type": "~:color", - "~:value": "{colors.white}", - "~:description": null, - "~:modified-at": "~m1737542498291" - } - } - ], - [ - "shadows.default", - { - "~#penpot/token": { - "~:name": "shadows.default", - "~:type": "~:color", - "~:value": "rgba({colors.black}, 0.3)", - "~:description": null, - "~:modified-at": "~m1737542498291" - } - } - ], - [ - "fg.muted", - { - "~#penpot/token": { - "~:name": "fg.muted", - "~:type": "~:color", - "~:value": "{colors.gray.300}", - "~:description": null, - "~:modified-at": "~m1737542498291" - } - } - ], - [ - "fg.default", - { - "~#penpot/token": { - "~:name": "fg.default", - "~:type": "~:color", - "~:value": "{colors.white}", - "~:description": null, - "~:modified-at": "~m1737542498291" - } - } - ], - [ - "fg.subtle", - { - "~#penpot/token": { - "~:name": "fg.subtle", - "~:type": "~:color", - "~:value": "{colors.gray.500}", - "~:description": null, - "~:modified-at": "~m1737542498291" - } - } - ], - [ - "bg.default", - { - "~#penpot/token": { - "~:name": "bg.default", - "~:type": "~:color", - "~:value": "{colors.gray.900}", - "~:description": null, - "~:modified-at": "~m1737542498291" - } - } - ] - ] - } - } + } + } + ] + ] } ], [ @@ -1742,7 +1750,7 @@ "~:is-source": false, "~:modified-at": "~m1737542746842", "~:sets": { - "~#set": ["light", "theme", "core"] + "~#set": ["LightDark/light", "theme", "core"] } } } @@ -1757,7 +1765,7 @@ "~:is-source": false, "~:modified-at": "~m1737542746842", "~:sets": { - "~#set": ["dark", "theme", "core"] + "~#set": ["LightDark/dark", "theme", "core"] } } } @@ -1779,7 +1787,7 @@ "~:is-source": false, "~:modified-at": "~m1737542683555", "~:sets": { - "~#set": ["light", "theme", "core"] + "~#set": ["LightDark/light", "theme", "core"] } } } diff --git a/frontend/playwright/ui/pages/WorkspacePage.js b/frontend/playwright/ui/pages/WorkspacePage.js index 06641a90c..20b694f92 100644 --- a/frontend/playwright/ui/pages/WorkspacePage.js +++ b/frontend/playwright/ui/pages/WorkspacePage.js @@ -88,6 +88,9 @@ export class WorkspacePage extends BaseWebSocketPage { this.tokensUpdateCreateModal = page.getByTestId( "token-update-create-modal", ); + this.tokenThemeUpdateCreateModal = page.getByTestId( + "token-theme-update-create-modal", + ); this.tokenThemesSetsSidebar = page.getByTestId("token-themes-sets-sidebar"); this.tokensSidebar = page.getByTestId("tokens-sidebar"); this.tokenSetItems = page.getByTestId("tokens-set-item"); diff --git a/frontend/playwright/ui/specs/tokens.spec.js b/frontend/playwright/ui/specs/tokens.spec.js index 21ee5ead8..98b8f7d10 100644 --- a/frontend/playwright/ui/specs/tokens.spec.js +++ b/frontend/playwright/ui/specs/tokens.spec.js @@ -54,6 +54,7 @@ const setupTokensFile = async (page) => { return { workspacePage, tokensUpdateCreateModal: workspacePage.tokensUpdateCreateModal, + tokenThemeUpdateCreateModal: workspacePage.tokenThemeUpdateCreateModal, tokenThemesSetsSidebar: workspacePage.tokenThemesSetsSidebar, tokenSetItems: workspacePage.tokenSetItems, tokenSetGroupItems: workspacePage.tokenSetGroupItems, @@ -183,6 +184,89 @@ test.describe("Tokens: Tokens Tab", () => { expect(colorTokenChanged).toBeVisible(); }); + test("User edits theme and activates it in the sidebar", async ({ page }) => { + const { + workspacePage, + tokensUpdateCreateModal, + tokenThemesSetsSidebar, + tokensSidebar, + tokenContextMenuForToken, + tokenThemeUpdateCreateModal, + } = await setupTokensFile(page); + + await expect(tokenThemesSetsSidebar).toBeVisible(); + + await tokenThemesSetsSidebar.getByRole("button", { name: "Edit" }).click(); + + await expect(tokenThemeUpdateCreateModal).toBeVisible(); + await tokenThemeUpdateCreateModal + .getByRole("button", { name: "sets" }) + .first() + .click(); + + await tokenThemeUpdateCreateModal.getByLabel("Theme").fill("Changed"); + + const lightDarkSetGroup = tokenThemeUpdateCreateModal.getByRole("button", { + name: "LightDark", + exact: true, + }); + await expect(lightDarkSetGroup).toBeVisible(); + const lightSet = tokenThemeUpdateCreateModal.getByRole("button", { + name: "light", + exact: true, + }); + const darkSet = tokenThemeUpdateCreateModal.getByRole("button", { + name: "dark", + exact: true, + }); + + // Mixed set group + await expect(lightSet.getByRole("checkbox")).toBeChecked(); + await expect(darkSet.getByRole("checkbox")).not.toBeChecked(); + + // Disable all + await lightDarkSetGroup.getByRole("checkbox").click(); + await expect(lightSet.getByRole("checkbox")).not.toBeChecked(); + await expect(darkSet.getByRole("checkbox")).not.toBeChecked(); + + // Enable all + await lightDarkSetGroup.getByRole("checkbox").click(); + await expect(lightSet.getByRole("checkbox")).toBeChecked(); + await expect(darkSet.getByRole("checkbox")).toBeChecked(); + + await tokenThemeUpdateCreateModal + .getByRole("button", { + name: "save theme", + }) + .click(); + + await expect( + tokenThemeUpdateCreateModal.getByText("Changed" + "4 sets"), + ).toBeVisible(); + + await tokenThemeUpdateCreateModal + .getByRole("button", { name: "Close" }) + .click(); + await expect(tokenThemeUpdateCreateModal).not.toBeVisible(); + + const themeSelect = tokenThemesSetsSidebar.getByRole("combobox"); + + await themeSelect.click(); + await themeSelect.getByRole("option", { name: "Changed" }).click(); + + const sidebarLightSet = tokenThemesSetsSidebar.getByRole("button", { + name: "light", + exact: true, + }); + const sidebarDarkSet = tokenThemesSetsSidebar.getByRole("button", { + name: "dark", + exact: true, + }); + + await expect(sidebarLightSet.getByRole("checkbox")).toBeChecked(); + await expect(sidebarDarkSet.getByRole("checkbox")).toBeChecked(); + }); + test("User creates grouped color token", async ({ page }) => { const { workspacePage, tokensUpdateCreateModal, tokenThemesSetsSidebar } = await setupEmptyTokensFile(page); @@ -251,7 +335,7 @@ test.describe("Tokens: Sets Tab", () => { // Create set in group await tokenThemesSetsSidebar - .getByRole("button", { name: "Collapse core" }) + .getByRole("button", { name: "core" }) .click({ button: "right" }); await expect(tokenContextMenuForSet).toBeVisible(); await tokenContextMenuForSet.getByText("Add set to this group").click(); diff --git a/frontend/src/app/main/ui/workspace/tokens/modals/themes.cljs b/frontend/src/app/main/ui/workspace/tokens/modals/themes.cljs index 8e3b935a9..21d26f3e2 100644 --- a/frontend/src/app/main/ui/workspace/tokens/modals/themes.cljs +++ b/frontend/src/app/main/ui/workspace/tokens/modals/themes.cljs @@ -158,7 +158,7 @@ :on-click create-theme} (tr "workspace.token.create-theme-title")]]])) -(mf/defc theme-inputs +(mf/defc theme-inputs* [{:keys [theme on-change-field]}] (let [theme-groups (mf/deref refs/workspace-token-theme-groups) theme-name-ref (mf/use-ref (:name theme)) @@ -166,9 +166,14 @@ {:label group :id group}) theme-groups) - on-update-group (partial on-change-field :group) + on-update-group + (mf/use-fn + (mf/deps on-change-field) + #(on-change-field :group %)) + on-update-name (mf/use-fn + (mf/deps on-change-field) (fn [event] (let [value (-> event dom/get-target dom/get-value)] (on-change-field :name value) @@ -187,9 +192,10 @@ :label (tr "workspace.token.label.theme") :type "text" :on-change on-update-name - :value (mf/ref-val theme-name-ref)}]]])) + :value (mf/ref-val theme-name-ref) + :auto-focus true}]]])) -(mf/defc theme-modal-buttons +(mf/defc theme-modal-buttons* [{:keys [close-modal on-save-form disabled?] :as props}] [:* [:> button* {:variant "secondary" @@ -206,44 +212,55 @@ [{:keys [set-state]}] (let [theme (ctob/make-token-theme :name "") on-back #(set-state (constantly {:type :themes-overview})) - on-submit (mf/use-fn - (fn [theme] - (st/emit! (ptk/event ::ev/event {::ev/name "create-tokens-theme"})) - (st/emit! (wdt/create-token-theme theme)))) - - theme-state (mf/use-state theme) - disabled? (-> (:name @theme-state) + theme-state* (mf/use-state theme) + theme-state (deref theme-state*) + disabled? (-> (:name theme-state) (str/trim) (str/empty?)) - on-change-field (fn [field value] - (swap! theme-state #(assoc % field value))) - on-save-form (mf/use-callback - (mf/deps theme-state on-submit) - (fn [e] - (dom/prevent-default e) - (let [theme (-> @theme-state - (update :name str/trim) - (update :group str/trim) - (update :description str/trim))] - (when-not (str/empty? (:name theme)) - (on-submit theme))) - (on-back))) - close-modal (mf/use-fn - (fn [e] - (dom/prevent-default e) - (st/emit! (modal/hide))))] + + on-change-field + (mf/use-fn + (fn [field value] + (swap! theme-state* #(assoc % field value)))) + + on-save-form + (mf/use-callback + (mf/deps theme-state) + (fn [e] + (dom/prevent-default e) + (let [theme (-> theme-state + (update :name str/trim) + (update :group str/trim) + (update :description str/trim))] + (when-not (str/empty? (:name theme)) + (st/emit! (ptk/event ::ev/event {::ev/name "create-tokens-theme"})) + (st/emit! (wdt/create-token-theme theme)))) + (on-back))) + + close-modal + (mf/use-fn + (fn [e] + (dom/prevent-default e) + (st/emit! (modal/hide))))] + [:div {:class (stl/css :themes-modal-wrapper)} [:> heading* {:level 2 :typography "headline-medium" :class (stl/css :themes-modal-title)} (tr "workspace.token.create-theme-title")] [:form {:on-submit on-save-form} [:div {:class (stl/css :create-theme-wrapper)} - [:& theme-inputs {:theme theme - :on-change-field on-change-field}] + [:> theme-inputs* {:theme theme + :on-change-field on-change-field}] [:div {:class (stl/css :button-footer)} - [:& theme-modal-buttons {:close-modal close-modal - :on-save-form on-save-form - :disabled? disabled?}]]]]])) + [:> theme-modal-buttons* {:close-modal close-modal + :on-save-form on-save-form + :disabled? disabled?}]]]]])) + +(defn- make-lib-with-theme [theme sets] + (-> (ctob/make-tokens-lib) + (ctob/add-theme theme) + (ctob/add-sets sets) + (ctob/activate-theme (:group theme) (:name theme)))) (mf/defc controlled-edit-theme [{:keys [state set-state]}] @@ -252,30 +269,29 @@ ordered-token-sets (mf/deref refs/workspace-ordered-token-sets) token-sets (mf/deref refs/workspace-token-sets-tree) theme (mf/deref (refs/workspace-token-theme theme-group theme-name)) - theme-state (mf/use-state theme) - lib (-> (ctob/make-tokens-lib) - (ctob/add-theme @theme-state) - (ctob/add-sets ordered-token-sets) - (ctob/activate-theme (:group @theme-state) (:name @theme-state))) + + theme-state* (mf/use-state theme) + theme-state (deref theme-state*) + lib (make-lib-with-theme theme-state ordered-token-sets) ;; Form / Modal handlers on-back #(set-state (constantly {:type :themes-overview})) on-submit #(st/emit! (wdt/update-token-theme [(:group theme) (:name theme)] %)) - disabled? (-> (:name @theme-state) + disabled? (-> (:name theme-state) (str/trim) (str/empty?)) on-change-field (mf/use-fn (fn [field value] - (swap! theme-state #(assoc % field value)))) + (swap! theme-state* #(assoc % field value)))) on-save-form - (mf/use-callback + (mf/use-fn (mf/deps theme-state on-submit) (fn [e] (dom/prevent-default e) - (let [theme (-> @theme-state + (let [theme (-> theme-state (update :name str/trim) (update :group str/trim) (update :description str/trim))] @@ -298,28 +314,30 @@ ;; Sets tree handlers token-set-group-active? - (mf/use-callback + (mf/use-fn (mf/deps theme-state) (fn [group-path] (ctob/sets-at-path-all-active? lib group-path))) token-set-active? - (mf/use-callback + (mf/use-fn (mf/deps theme-state) (fn [set-name] - (get-in @theme-state [:sets set-name]))) + (get-in theme-state [:sets set-name]))) on-toggle-token-set - (mf/use-callback + (mf/use-fn (mf/deps theme-state) (fn [set-name] - (swap! theme-state #(ctob/toggle-set % set-name)))) + (swap! theme-state* #(ctob/toggle-set % set-name)))) on-toggle-token-set-group - (mf/use-callback - (mf/deps theme-state) + (mf/use-fn + (mf/deps theme-state ordered-token-sets) (fn [group-path] - (swap! theme-state #(clt/toggle-token-set-group group-path lib %)))) + (swap! theme-state* (fn [theme'] + (let [lib' (make-lib-with-theme theme' ordered-token-sets)] + (clt/toggle-token-set-group group-path lib' theme')))))) on-click-token-set (mf/use-callback @@ -340,8 +358,8 @@ [:> icon* {:icon-id ic/arrow-left :aria-hidden true}] (tr "workspace.token.back-to-themes")] - [:& theme-inputs {:theme theme - :on-change-field on-change-field}] + [:> theme-inputs* {:theme theme + :on-change-field on-change-field}] [:> text* {:as "span" :typography "body-small" :class (stl/css :select-sets-message)} (tr "workspace.token.set-selection-theme")] [:div {:class (stl/css :sets-list-wrapper)} @@ -364,9 +382,9 @@ :on-click on-delete-token} (tr "labels.delete")] [:div {:class (stl/css :button-footer)} - [:& theme-modal-buttons {:close-modal close-modal - :on-save-form on-save-form - :disabled? disabled?}]]]]]])) + [:> theme-modal-buttons* {:close-modal close-modal + :on-save-form on-save-form + :disabled? disabled?}]]]]]])) (mf/defc themes-modal-body [_] @@ -390,7 +408,8 @@ [_args] (let [handle-close-dialog (mf/use-callback #(st/emit! (modal/hide)))] [:div {:class (stl/css :modal-overlay)} - [:div {:class (stl/css :modal-dialog)} + [:div {:class (stl/css :modal-dialog) + :data-testid "token-theme-update-create-modal"} [:> icon-button* {:class (stl/css :close-btn) :on-click handle-close-dialog :aria-label (tr "labels.close") diff --git a/frontend/src/app/main/ui/workspace/tokens/sets.cljs b/frontend/src/app/main/ui/workspace/tokens/sets.cljs index 92708d603..96a7074d7 100644 --- a/frontend/src/app/main/ui/workspace/tokens/sets.cljs +++ b/frontend/src/app/main/ui/workspace/tokens/sets.cljs @@ -107,6 +107,8 @@ editing?' (editing? editing-id) collapsed? (some? (get @collapsed-paths tree-path)) can-edit? (:can-edit (deref refs/permissions)) + ;; Used by playwright to get the correct item by label + label-id (str editing-id "-label") on-context-menu (mf/use-fn @@ -165,6 +167,7 @@ [:div {:ref dref :role "button" + :aria-labelledby label-id :data-testid "tokens-set-group-item" :style {"--tree-depth" tree-depth} :class (stl/css-case :set-item-container true @@ -188,7 +191,8 @@ :on-submit on-edit-submit'}] [:* [:div {:class (stl/css :set-name) - :on-double-click on-double-click} + :on-double-click on-double-click + :id label-id} label] [:& checkbox {:on-click on-checkbox-click