From dcd306bc5ca7a0a8d796b1a647c3c24ab7177bc9 Mon Sep 17 00:00:00 2001 From: Alex Grozav Date: Mon, 16 Mar 2026 20:27:20 +0200 Subject: [PATCH] fix(editor): Prevent unwanted UI elements appearing when execute button is loading (#27003) --- .gitignore | 1 + .../src/components/N8nButton/Button.stories.ts | 11 ++++------- .../design-system/src/components/N8nButton/Button.vue | 3 +++ .../__snapshots__/N8nPromptInput.test.ts.snap | 2 ++ .../elements/buttons/CanvasRunWorkflowButton.vue | 5 +++++ .../nodes/render-types/parts/CanvasNodeTrigger.vue | 5 +++++ 6 files changed, 20 insertions(+), 7 deletions(-) diff --git a/.gitignore b/.gitignore index 59f4efb0832..e9aeb73e31d 100644 --- a/.gitignore +++ b/.gitignore @@ -56,3 +56,4 @@ packages/cli/src/commands/export/outputs .data/ .claude/settings.local.json lefthook-local.yml +.playwright-mcp diff --git a/packages/frontend/@n8n/design-system/src/components/N8nButton/Button.stories.ts b/packages/frontend/@n8n/design-system/src/components/N8nButton/Button.stories.ts index c979e3c0afa..93a57b20091 100644 --- a/packages/frontend/@n8n/design-system/src/components/N8nButton/Button.stories.ts +++ b/packages/frontend/@n8n/design-system/src/components/N8nButton/Button.stories.ts @@ -171,13 +171,10 @@ export const IconOnly: Story = { template: `
- - - - - - - + + + +
diff --git a/packages/frontend/@n8n/design-system/src/components/N8nButton/Button.vue b/packages/frontend/@n8n/design-system/src/components/N8nButton/Button.vue index 5018789a17f..e4981b99d8f 100644 --- a/packages/frontend/@n8n/design-system/src/components/N8nButton/Button.vue +++ b/packages/frontend/@n8n/design-system/src/components/N8nButton/Button.vue @@ -96,6 +96,7 @@ const handleClick = (event: MouseEvent) => { :aria-busy="loading || undefined" :tabindex="componentTag === 'a' && isDisabled ? -1 : undefined" :class="classes" + :data-icon-only="iconOnly ? 'true' : undefined" aria-live="polite" @click="handleClick" > @@ -390,6 +391,8 @@ const handleClick = (event: MouseEvent) => { &.iconOnly { width: var(--button--height); padding: 0; + justify-content: center; + align-items: center; > * { width: var(--button--height); diff --git a/packages/frontend/@n8n/design-system/src/components/N8nPromptInput/__snapshots__/N8nPromptInput.test.ts.snap b/packages/frontend/@n8n/design-system/src/components/N8nPromptInput/__snapshots__/N8nPromptInput.test.ts.snap index 8498100f29a..1d526bfb5b3 100644 --- a/packages/frontend/@n8n/design-system/src/components/N8nPromptInput/__snapshots__/N8nPromptInput.test.ts.snap +++ b/packages/frontend/@n8n/design-system/src/components/N8nPromptInput/__snapshots__/N8nPromptInput.test.ts.snap @@ -42,6 +42,7 @@ exports[`N8nPromptInput > rendering > should render correctly with default props aria-label="Send" aria-live="polite" class="button button solid small iconOnly disabled sendButton" + data-icon-only="true" data-test-id="send-message-button" disabled="" type="button" @@ -131,6 +132,7 @@ exports[`N8nPromptInput > rendering > should render streaming state without disa aria-label="Stop" aria-live="polite" class="button button solid small iconOnly stopButton" + data-icon-only="true" data-test-id="send-message-button" type="button" > diff --git a/packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/buttons/CanvasRunWorkflowButton.vue b/packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/buttons/CanvasRunWorkflowButton.vue index 706af28c061..46f2ac34a2d 100644 --- a/packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/buttons/CanvasRunWorkflowButton.vue +++ b/packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/buttons/CanvasRunWorkflowButton.vue @@ -167,6 +167,11 @@ function getNodeTypeByName(name: string): INodeTypeDescription | null { border-top-right-radius: 0; border-bottom-right-radius: 0; } + + .split &[data-icon-only] { + padding-inline-start: 0; + width: var(--spacing--2xl); + } } .divider { diff --git a/packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/nodes/render-types/parts/CanvasNodeTrigger.vue b/packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/nodes/render-types/parts/CanvasNodeTrigger.vue index 6a44ddb4b87..f82b8f6dbea 100644 --- a/packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/nodes/render-types/parts/CanvasNodeTrigger.vue +++ b/packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/nodes/render-types/parts/CanvasNodeTrigger.vue @@ -163,6 +163,11 @@ async function handleClickExecute() { transform-origin: center right; } + /* Override N8nButton's .disabled { opacity: 0.5 } which has higher specificity */ + & button[disabled] { + opacity: 0; + } + &.interactive.hovered button { opacity: 1; translate: 0 0;