🐛 Fix toggling set groups in theme modal not working (#5733)

This commit is contained in:
Florian Schrödl 2025-02-05 12:21:21 +01:00 committed by GitHub
parent 48acc8715b
commit 86e0f8ad34
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 441 additions and 323 deletions

View file

@ -1371,271 +1371,279 @@
} }
], ],
[ [
"S-light", "G-LightDark",
{ {
"~#penpot/token-set": { "~#ordered-map": [
"~:name": "light", [
"~:description": null, "S-light",
"~:modified-at": "~m1737542498290", {
"~:tokens": { "~#penpot/token-set": {
"~#ordered-map": [ "~:name": "LightDark/light",
[ "~:description": null,
"accent.default", "~:modified-at": "~m1737542498290",
{ "~:tokens": {
"~#penpot/token": { "~#ordered-map": [
"~:name": "accent.default", [
"~:type": "~:color", "accent.default",
"~:value": "{colors.indigo.400}", {
"~:description": null, "~#penpot/token": {
"~:modified-at": "~m1737542498290" "~: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", "S-dark",
"~:type": "~:color", {
"~:value": "{colors.gray.100}", "~#penpot/token-set": {
"~:description": null, "~:name": "LightDark/dark",
"~:modified-at": "~m1737542498290" "~: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, "~:is-source": false,
"~:modified-at": "~m1737542746842", "~:modified-at": "~m1737542746842",
"~:sets": { "~:sets": {
"~#set": ["light", "theme", "core"] "~#set": ["LightDark/light", "theme", "core"]
} }
} }
} }
@ -1757,7 +1765,7 @@
"~:is-source": false, "~:is-source": false,
"~:modified-at": "~m1737542746842", "~:modified-at": "~m1737542746842",
"~:sets": { "~:sets": {
"~#set": ["dark", "theme", "core"] "~#set": ["LightDark/dark", "theme", "core"]
} }
} }
} }
@ -1779,7 +1787,7 @@
"~:is-source": false, "~:is-source": false,
"~:modified-at": "~m1737542683555", "~:modified-at": "~m1737542683555",
"~:sets": { "~:sets": {
"~#set": ["light", "theme", "core"] "~#set": ["LightDark/light", "theme", "core"]
} }
} }
} }

View file

@ -88,6 +88,9 @@ export class WorkspacePage extends BaseWebSocketPage {
this.tokensUpdateCreateModal = page.getByTestId( this.tokensUpdateCreateModal = page.getByTestId(
"token-update-create-modal", "token-update-create-modal",
); );
this.tokenThemeUpdateCreateModal = page.getByTestId(
"token-theme-update-create-modal",
);
this.tokenThemesSetsSidebar = page.getByTestId("token-themes-sets-sidebar"); this.tokenThemesSetsSidebar = page.getByTestId("token-themes-sets-sidebar");
this.tokensSidebar = page.getByTestId("tokens-sidebar"); this.tokensSidebar = page.getByTestId("tokens-sidebar");
this.tokenSetItems = page.getByTestId("tokens-set-item"); this.tokenSetItems = page.getByTestId("tokens-set-item");

View file

@ -54,6 +54,7 @@ const setupTokensFile = async (page) => {
return { return {
workspacePage, workspacePage,
tokensUpdateCreateModal: workspacePage.tokensUpdateCreateModal, tokensUpdateCreateModal: workspacePage.tokensUpdateCreateModal,
tokenThemeUpdateCreateModal: workspacePage.tokenThemeUpdateCreateModal,
tokenThemesSetsSidebar: workspacePage.tokenThemesSetsSidebar, tokenThemesSetsSidebar: workspacePage.tokenThemesSetsSidebar,
tokenSetItems: workspacePage.tokenSetItems, tokenSetItems: workspacePage.tokenSetItems,
tokenSetGroupItems: workspacePage.tokenSetGroupItems, tokenSetGroupItems: workspacePage.tokenSetGroupItems,
@ -183,6 +184,89 @@ test.describe("Tokens: Tokens Tab", () => {
expect(colorTokenChanged).toBeVisible(); 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 }) => { test("User creates grouped color token", async ({ page }) => {
const { workspacePage, tokensUpdateCreateModal, tokenThemesSetsSidebar } = const { workspacePage, tokensUpdateCreateModal, tokenThemesSetsSidebar } =
await setupEmptyTokensFile(page); await setupEmptyTokensFile(page);
@ -251,7 +335,7 @@ test.describe("Tokens: Sets Tab", () => {
// Create set in group // Create set in group
await tokenThemesSetsSidebar await tokenThemesSetsSidebar
.getByRole("button", { name: "Collapse core" }) .getByRole("button", { name: "core" })
.click({ button: "right" }); .click({ button: "right" });
await expect(tokenContextMenuForSet).toBeVisible(); await expect(tokenContextMenuForSet).toBeVisible();
await tokenContextMenuForSet.getByText("Add set to this group").click(); await tokenContextMenuForSet.getByText("Add set to this group").click();

View file

@ -158,7 +158,7 @@
:on-click create-theme} :on-click create-theme}
(tr "workspace.token.create-theme-title")]]])) (tr "workspace.token.create-theme-title")]]]))
(mf/defc theme-inputs (mf/defc theme-inputs*
[{:keys [theme on-change-field]}] [{:keys [theme on-change-field]}]
(let [theme-groups (mf/deref refs/workspace-token-theme-groups) (let [theme-groups (mf/deref refs/workspace-token-theme-groups)
theme-name-ref (mf/use-ref (:name theme)) theme-name-ref (mf/use-ref (:name theme))
@ -166,9 +166,14 @@
{:label group {:label group
:id group}) :id group})
theme-groups) 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 on-update-name
(mf/use-fn (mf/use-fn
(mf/deps on-change-field)
(fn [event] (fn [event]
(let [value (-> event dom/get-target dom/get-value)] (let [value (-> event dom/get-target dom/get-value)]
(on-change-field :name value) (on-change-field :name value)
@ -187,9 +192,10 @@
:label (tr "workspace.token.label.theme") :label (tr "workspace.token.label.theme")
:type "text" :type "text"
:on-change on-update-name :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}] [{:keys [close-modal on-save-form disabled?] :as props}]
[:* [:*
[:> button* {:variant "secondary" [:> button* {:variant "secondary"
@ -206,44 +212,55 @@
[{:keys [set-state]}] [{:keys [set-state]}]
(let [theme (ctob/make-token-theme :name "") (let [theme (ctob/make-token-theme :name "")
on-back #(set-state (constantly {:type :themes-overview})) on-back #(set-state (constantly {:type :themes-overview}))
on-submit (mf/use-fn theme-state* (mf/use-state theme)
(fn [theme] theme-state (deref theme-state*)
(st/emit! (ptk/event ::ev/event {::ev/name "create-tokens-theme"})) disabled? (-> (:name theme-state)
(st/emit! (wdt/create-token-theme theme))))
theme-state (mf/use-state theme)
disabled? (-> (:name @theme-state)
(str/trim) (str/trim)
(str/empty?)) (str/empty?))
on-change-field (fn [field value]
(swap! theme-state #(assoc % field value))) on-change-field
on-save-form (mf/use-callback (mf/use-fn
(mf/deps theme-state on-submit) (fn [field value]
(fn [e] (swap! theme-state* #(assoc % field value))))
(dom/prevent-default e)
(let [theme (-> @theme-state on-save-form
(update :name str/trim) (mf/use-callback
(update :group str/trim) (mf/deps theme-state)
(update :description str/trim))] (fn [e]
(when-not (str/empty? (:name theme)) (dom/prevent-default e)
(on-submit theme))) (let [theme (-> theme-state
(on-back))) (update :name str/trim)
close-modal (mf/use-fn (update :group str/trim)
(fn [e] (update :description str/trim))]
(dom/prevent-default e) (when-not (str/empty? (:name theme))
(st/emit! (modal/hide))))] (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)} [:div {:class (stl/css :themes-modal-wrapper)}
[:> heading* {:level 2 :typography "headline-medium" :class (stl/css :themes-modal-title)} [:> heading* {:level 2 :typography "headline-medium" :class (stl/css :themes-modal-title)}
(tr "workspace.token.create-theme-title")] (tr "workspace.token.create-theme-title")]
[:form {:on-submit on-save-form} [:form {:on-submit on-save-form}
[:div {:class (stl/css :create-theme-wrapper)} [:div {:class (stl/css :create-theme-wrapper)}
[:& theme-inputs {:theme theme [:> theme-inputs* {:theme theme
:on-change-field on-change-field}] :on-change-field on-change-field}]
[:div {:class (stl/css :button-footer)} [:div {:class (stl/css :button-footer)}
[:& theme-modal-buttons {:close-modal close-modal [:> theme-modal-buttons* {:close-modal close-modal
:on-save-form on-save-form :on-save-form on-save-form
:disabled? disabled?}]]]]])) :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 (mf/defc controlled-edit-theme
[{:keys [state set-state]}] [{:keys [state set-state]}]
@ -252,30 +269,29 @@
ordered-token-sets (mf/deref refs/workspace-ordered-token-sets) ordered-token-sets (mf/deref refs/workspace-ordered-token-sets)
token-sets (mf/deref refs/workspace-token-sets-tree) token-sets (mf/deref refs/workspace-token-sets-tree)
theme (mf/deref (refs/workspace-token-theme theme-group theme-name)) theme (mf/deref (refs/workspace-token-theme theme-group theme-name))
theme-state (mf/use-state theme)
lib (-> (ctob/make-tokens-lib) theme-state* (mf/use-state theme)
(ctob/add-theme @theme-state) theme-state (deref theme-state*)
(ctob/add-sets ordered-token-sets) lib (make-lib-with-theme theme-state ordered-token-sets)
(ctob/activate-theme (:group @theme-state) (:name @theme-state)))
;; Form / Modal handlers ;; Form / Modal handlers
on-back #(set-state (constantly {:type :themes-overview})) on-back #(set-state (constantly {:type :themes-overview}))
on-submit #(st/emit! (wdt/update-token-theme [(:group theme) (:name theme)] %)) on-submit #(st/emit! (wdt/update-token-theme [(:group theme) (:name theme)] %))
disabled? (-> (:name @theme-state) disabled? (-> (:name theme-state)
(str/trim) (str/trim)
(str/empty?)) (str/empty?))
on-change-field on-change-field
(mf/use-fn (mf/use-fn
(fn [field value] (fn [field value]
(swap! theme-state #(assoc % field value)))) (swap! theme-state* #(assoc % field value))))
on-save-form on-save-form
(mf/use-callback (mf/use-fn
(mf/deps theme-state on-submit) (mf/deps theme-state on-submit)
(fn [e] (fn [e]
(dom/prevent-default e) (dom/prevent-default e)
(let [theme (-> @theme-state (let [theme (-> theme-state
(update :name str/trim) (update :name str/trim)
(update :group str/trim) (update :group str/trim)
(update :description str/trim))] (update :description str/trim))]
@ -298,28 +314,30 @@
;; Sets tree handlers ;; Sets tree handlers
token-set-group-active? token-set-group-active?
(mf/use-callback (mf/use-fn
(mf/deps theme-state) (mf/deps theme-state)
(fn [group-path] (fn [group-path]
(ctob/sets-at-path-all-active? lib group-path))) (ctob/sets-at-path-all-active? lib group-path)))
token-set-active? token-set-active?
(mf/use-callback (mf/use-fn
(mf/deps theme-state) (mf/deps theme-state)
(fn [set-name] (fn [set-name]
(get-in @theme-state [:sets set-name]))) (get-in theme-state [:sets set-name])))
on-toggle-token-set on-toggle-token-set
(mf/use-callback (mf/use-fn
(mf/deps theme-state) (mf/deps theme-state)
(fn [set-name] (fn [set-name]
(swap! theme-state #(ctob/toggle-set % set-name)))) (swap! theme-state* #(ctob/toggle-set % set-name))))
on-toggle-token-set-group on-toggle-token-set-group
(mf/use-callback (mf/use-fn
(mf/deps theme-state) (mf/deps theme-state ordered-token-sets)
(fn [group-path] (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 on-click-token-set
(mf/use-callback (mf/use-callback
@ -340,8 +358,8 @@
[:> icon* {:icon-id ic/arrow-left :aria-hidden true}] [:> icon* {:icon-id ic/arrow-left :aria-hidden true}]
(tr "workspace.token.back-to-themes")] (tr "workspace.token.back-to-themes")]
[:& theme-inputs {:theme theme [:> theme-inputs* {:theme theme
:on-change-field on-change-field}] :on-change-field on-change-field}]
[:> text* {:as "span" :typography "body-small" :class (stl/css :select-sets-message)} [:> text* {:as "span" :typography "body-small" :class (stl/css :select-sets-message)}
(tr "workspace.token.set-selection-theme")] (tr "workspace.token.set-selection-theme")]
[:div {:class (stl/css :sets-list-wrapper)} [:div {:class (stl/css :sets-list-wrapper)}
@ -364,9 +382,9 @@
:on-click on-delete-token} :on-click on-delete-token}
(tr "labels.delete")] (tr "labels.delete")]
[:div {:class (stl/css :button-footer)} [:div {:class (stl/css :button-footer)}
[:& theme-modal-buttons {:close-modal close-modal [:> theme-modal-buttons* {:close-modal close-modal
:on-save-form on-save-form :on-save-form on-save-form
:disabled? disabled?}]]]]]])) :disabled? disabled?}]]]]]]))
(mf/defc themes-modal-body (mf/defc themes-modal-body
[_] [_]
@ -390,7 +408,8 @@
[_args] [_args]
(let [handle-close-dialog (mf/use-callback #(st/emit! (modal/hide)))] (let [handle-close-dialog (mf/use-callback #(st/emit! (modal/hide)))]
[:div {:class (stl/css :modal-overlay)} [: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) [:> icon-button* {:class (stl/css :close-btn)
:on-click handle-close-dialog :on-click handle-close-dialog
:aria-label (tr "labels.close") :aria-label (tr "labels.close")

View file

@ -107,6 +107,8 @@
editing?' (editing? editing-id) editing?' (editing? editing-id)
collapsed? (some? (get @collapsed-paths tree-path)) collapsed? (some? (get @collapsed-paths tree-path))
can-edit? (:can-edit (deref refs/permissions)) 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 on-context-menu
(mf/use-fn (mf/use-fn
@ -165,6 +167,7 @@
[:div {:ref dref [:div {:ref dref
:role "button" :role "button"
:aria-labelledby label-id
:data-testid "tokens-set-group-item" :data-testid "tokens-set-group-item"
:style {"--tree-depth" tree-depth} :style {"--tree-depth" tree-depth}
:class (stl/css-case :set-item-container true :class (stl/css-case :set-item-container true
@ -188,7 +191,8 @@
:on-submit on-edit-submit'}] :on-submit on-edit-submit'}]
[:* [:*
[:div {:class (stl/css :set-name) [:div {:class (stl/css :set-name)
:on-double-click on-double-click} :on-double-click on-double-click
:id label-id}
label] label]
[:& checkbox [:& checkbox
{:on-click on-checkbox-click {:on-click on-checkbox-click