From 03e8542648b690b524f3dcad99508e4c77ebd6f3 Mon Sep 17 00:00:00 2001 From: Taylor Ho Date: Wed, 12 Aug 2026 12:25:12 -0700 Subject: [PATCH] Fix workflow node selection styling Signed-off-by: Taylor Ho --- .../workflows/ui/WorkflowFormBuilder.tsx | 215 +++++++++--------- desktop/tests/e2e/workflows.spec.ts | 19 +- 2 files changed, 127 insertions(+), 107 deletions(-) diff --git a/desktop/src/features/workflows/ui/WorkflowFormBuilder.tsx b/desktop/src/features/workflows/ui/WorkflowFormBuilder.tsx index f8d8ced0e..2ca2f4f59 100644 --- a/desktop/src/features/workflows/ui/WorkflowFormBuilder.tsx +++ b/desktop/src/features/workflows/ui/WorkflowFormBuilder.tsx @@ -244,10 +244,10 @@ function WorkflowNode({ "relative z-20 flex w-full items-center gap-3 text-left transition-colors", "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2", "rounded-full bg-muted/25 p-3 outline outline-2 outline-offset-4 outline-muted-foreground/0", - selected - ? "bg-muted/70 outline-muted-foreground/20" - : "hover:bg-muted/45", + "data-[selected=true]:bg-muted/70 data-[selected=true]:outline-muted-foreground/20", + "data-[selected=false]:hover:bg-muted/45", )} + data-selected={selected} disabled={disabled} onClick={onClick} type="button" @@ -255,10 +255,11 @@ function WorkflowNode({ {isNumbered ? number : icon} @@ -558,8 +559,8 @@ export function WorkflowFormBuilder({ {selectedNode ? ( -
-
-

- {selectedNode.type === "trigger" - ? "Trigger" - : `Step ${selectedNode.index + 1}`} -

- {selectedNode.type === "trigger" ? ( - - updateFormState({ - ...formState, - trigger: { on: triggerType }, - }) - } - options={TRIGGER_TYPES} - value={formState.trigger.on} - /> - ) : selectedStep ? ( - { - const next = { ...selectedStep, action }; - if (action === "call_webhook" && !next.method) { - next.method = "POST"; +
+
+
+

+ {selectedNode.type === "trigger" + ? "Trigger" + : `Step ${selectedNode.index + 1}`} +

+ {selectedNode.type === "trigger" ? ( + + updateFormState({ + ...formState, + trigger: { on: triggerType }, + }) } - updateStep(selectedNode.index, next); - }} - options={ACTION_TYPES} - value={selectedStep.action} - /> - ) : null} -
-
- {selectedNode.type === "step" && selectedStep ? ( + options={TRIGGER_TYPES} + value={formState.trigger.on} + /> + ) : selectedStep ? ( + { + const next = { ...selectedStep, action }; + if (action === "call_webhook" && !next.method) { + next.method = "POST"; + } + updateStep(selectedNode.index, next); + }} + options={ACTION_TYPES} + value={selectedStep.action} + /> + ) : null} +
+
+ {selectedNode.type === "step" && selectedStep ? ( + + ) : null} - ) : null} - +
-
-
- - + - {selectedNode.type === "trigger" ? ( -
- - updateFormState({ ...formState, trigger }) + + {selectedNode.type === "trigger" ? ( +
+ + updateFormState({ ...formState, trigger }) + } + trigger={formState.trigger} + /> +
+ ) : selectedStep ? ( + removeStep(selectedNode.index)} + onUpdate={(updated) => + updateStep(selectedNode.index, updated) } - trigger={formState.trigger} + showHeader={false} + step={selectedStep} + triggerType={formState.trigger.on} /> -
- ) : selectedStep ? ( - removeStep(selectedNode.index)} - onUpdate={(updated) => - updateStep(selectedNode.index, updated) - } - showHeader={false} - step={selectedStep} - triggerType={formState.trigger.on} - /> - ) : null} -
-
+ ) : null} + + +
) : null} diff --git a/desktop/tests/e2e/workflows.spec.ts b/desktop/tests/e2e/workflows.spec.ts index 0259dbc1e..2b83a579c 100644 --- a/desktop/tests/e2e/workflows.spec.ts +++ b/desktop/tests/e2e/workflows.spec.ts @@ -160,6 +160,8 @@ test("opens node configuration in a contextual inspector", async ({ page }) => { await dialog.getByRole("button", { name: "Add step" }).click(); await page.getByRole("menuitem", { name: "Send Message" }).click(); + const triggerNode = dialog.getByRole("button", { name: /^Trigger:/ }); + const stepNode = dialog.getByRole("button", { name: /^Step 1:/ }); await expect(inspector.getByLabel("Step ID")).toHaveValue("step_1"); await expect(inspector.getByLabel("Action")).toHaveAttribute( "data-value", @@ -167,6 +169,22 @@ test("opens node configuration in a contextual inspector", async ({ page }) => { ); await expect(inspector.getByLabel("Message text")).toBeVisible(); await expect(dialog.getByText("End", { exact: true })).toBeVisible(); + await expect(triggerNode).toHaveAttribute("aria-pressed", "false"); + await expect(stepNode).toHaveAttribute("aria-pressed", "true"); + expect( + await triggerNode.evaluate( + (element) => getComputedStyle(element).outlineColor, + ), + ).not.toBe( + await stepNode.evaluate( + (element) => getComputedStyle(element).outlineColor, + ), + ); + await expect + .poll(() => + inspector.evaluate((element) => getComputedStyle(element).padding), + ) + .toBe("16px"); await inspector.getByLabel("Action").click(); await page.getByRole("menuitem", { name: "Send DM" }).click(); @@ -176,7 +194,6 @@ test("opens node configuration in a contextual inspector", async ({ page }) => { ); await expect(inspector.getByLabel("To (pubkey)")).toBeVisible(); - const stepNode = dialog.getByRole("button", { name: /^Step 1:/ }); await inspector.getByLabel("Name (optional)").fill("Notify deployer"); await expect(stepNode).toContainText("Notify deployer"); await expect(stepNode).toContainText("Send DM");