From ee67e9e354ebc0be62d81dbb5b6e9a13099e6eb7 Mon Sep 17 00:00:00 2001 From: Suguru Inoue Date: Tue, 22 Jul 2025 11:39:14 +0200 Subject: [PATCH] feat(editor): Update styling of embedded NDV (no-changelog) (#17366) --- .../src/components/N8nTabs/Tabs.vue | 36 +++- packages/frontend/editor-ui/package.json | 1 + .../editor-ui/src/__tests__/data/canvas.ts | 1 + .../src/components/FreeAiCreditsCallout.vue | 62 +++--- .../editor-ui/src/components/NodeSettings.vue | 73 ++++--- .../src/components/NodeSettingsHeader.vue | 7 +- .../src/components/NodeSettingsTabs.vue | 3 + .../src/components/canvas/Canvas.vue | 10 + .../elements/buttons/CanvasControlButtons.vue | 5 +- .../canvas/elements/edges/CanvasEdge.test.ts | 8 +- .../canvas/elements/edges/CanvasEdge.vue | 21 +- .../elements/edges/CanvasEdgeToolbar.vue | 1 + .../elements/handles/CanvasHandleRenderer.vue | 6 +- .../render-types/CanvasHandleMainInput.vue | 3 +- .../render-types/CanvasHandleMainOutput.vue | 8 +- .../render-types/CanvasHandleNonMainInput.vue | 2 +- .../CanvasHandleNonMainOutput.vue | 2 +- .../render-types/parts/CanvasHandlePlus.vue | 9 + .../canvas/elements/nodes/CanvasNode.vue | 16 +- .../elements/nodes/CanvasNodeToolbar.vue | 7 +- .../nodes/render-types/CanvasNodeDefault.vue | 10 +- .../parts/CanvasNodeStatusIcons.vue | 75 ++++--- .../render-types/parts/CanvasNodeTrigger.vue | 9 + .../ExperimentalCanvasNodeSettings.vue | 4 +- .../ExperimentalEmbeddedNdvActions.vue | 50 +++++ .../ExperimentalEmbeddedNdvHeader.vue | 90 ++++++++ .../ExperimentalEmbeddedNdvMapper.vue | 129 +++++++++++ .../ExperimentalEmbeddedNodeDetails.vue | 202 ++++++++---------- .../experimental/experimentalNdv.utils.ts | 34 ++- .../frontend/editor-ui/src/types/canvas.ts | 1 + pnpm-lock.yaml | 3 + 31 files changed, 623 insertions(+), 265 deletions(-) create mode 100644 packages/frontend/editor-ui/src/components/canvas/experimental/components/ExperimentalEmbeddedNdvActions.vue create mode 100644 packages/frontend/editor-ui/src/components/canvas/experimental/components/ExperimentalEmbeddedNdvHeader.vue create mode 100644 packages/frontend/editor-ui/src/components/canvas/experimental/components/ExperimentalEmbeddedNdvMapper.vue diff --git a/packages/frontend/@n8n/design-system/src/components/N8nTabs/Tabs.vue b/packages/frontend/@n8n/design-system/src/components/N8nTabs/Tabs.vue index 0104b138a8..ab5ed10a59 100644 --- a/packages/frontend/@n8n/design-system/src/components/N8nTabs/Tabs.vue +++ b/packages/frontend/@n8n/design-system/src/components/N8nTabs/Tabs.vue @@ -10,12 +10,14 @@ interface TabsProps { modelValue?: Value; options?: Array>; size?: 'small' | 'medium'; + variant?: 'modern' | 'legacy'; } withDefaults(defineProps(), { modelValue: undefined, options: () => [], size: 'medium', + variant: 'legacy', }); const scrollPosition = ref(0); @@ -69,7 +71,14 @@ const scrollRight = () => scroll(50); - {{ i18n.baseText('nodeSettings.communityNodeUnknown.installLink.text') }} - + @@ -182,14 +175,24 @@ function onEdgeLabelMouseLeave() { transition: stroke 0.3s ease, fill 0.3s ease; + stroke-width: calc(2 * var(--canvas-zoom-compensation-factor, 1)); + stroke-linecap: square; } .edgeLabelWrapper { transform: translateY(calc(var(--spacing-xs) * -1)); position: absolute; + + --label-translate-y: 0; + + &.straight { + --label-translate-y: -100%; + } } .edgeLabel { + transform: scale(var(--canvas-zoom-compensation-factor, 1)) translate(0, var(--label-translate-y)); + color: var(--color-text-base); font-size: var(--font-size-xs); background-color: hsla( var(--color-canvas-background-h), diff --git a/packages/frontend/editor-ui/src/components/canvas/elements/edges/CanvasEdgeToolbar.vue b/packages/frontend/editor-ui/src/components/canvas/elements/edges/CanvasEdgeToolbar.vue index e32c21de14..f5d8b7b8e3 100644 --- a/packages/frontend/editor-ui/src/components/canvas/elements/edges/CanvasEdgeToolbar.vue +++ b/packages/frontend/editor-ui/src/components/canvas/elements/edges/CanvasEdgeToolbar.vue @@ -66,6 +66,7 @@ function onDelete() { gap: var(--spacing-2xs); pointer-events: all; padding: var(--spacing-2xs); + transform: scale(var(--canvas-zoom-compensation-factor, 1)); } diff --git a/packages/frontend/editor-ui/src/components/canvas/elements/handles/CanvasHandleRenderer.vue b/packages/frontend/editor-ui/src/components/canvas/elements/handles/CanvasHandleRenderer.vue index 79340ba310..047d4e770a 100644 --- a/packages/frontend/editor-ui/src/components/canvas/elements/handles/CanvasHandleRenderer.vue +++ b/packages/frontend/editor-ui/src/components/canvas/elements/handles/CanvasHandleRenderer.vue @@ -166,8 +166,8 @@ provide(CanvasNodeHandleKey, { diff --git a/packages/frontend/editor-ui/src/components/canvas/elements/nodes/render-types/parts/CanvasNodeTrigger.vue b/packages/frontend/editor-ui/src/components/canvas/elements/nodes/render-types/parts/CanvasNodeTrigger.vue index d4bffc9045..6b4015ec07 100644 --- a/packages/frontend/editor-ui/src/components/canvas/elements/nodes/render-types/parts/CanvasNodeTrigger.vue +++ b/packages/frontend/editor-ui/src/components/canvas/elements/nodes/render-types/parts/CanvasNodeTrigger.vue @@ -17,6 +17,7 @@ const { disabled, readOnly, class: cls, + isExperimentalNdvActive, } = defineProps<{ name: string; type: string; @@ -24,6 +25,7 @@ const { disabled?: boolean; readOnly?: boolean; class?: string; + isExperimentalNdvActive: boolean; }>(); const style = useCssModule(); @@ -32,6 +34,7 @@ const containerClass = computed(() => ({ [style.container]: true, [style.interactive]: !disabled && !readOnly, [style.hovered]: !!hovered, + [style.isExperimentalNdvActive]: isExperimentalNdvActive, })); const router = useRouter(); @@ -126,6 +129,8 @@ async function handleClickExecute() { transition: translate 0.1s ease-in, opacity 0.1s ease-in; + transform: scale(var(--canvas-zoom-compensation-factor, 1)); + transform-origin: center right; } &.interactive.hovered button { @@ -133,6 +138,10 @@ async function handleClickExecute() { translate: 0 0; pointer-events: all; } + + &.isExperimentalNdvActive { + height: var(--spacing-2xl); + } } .bolt { diff --git a/packages/frontend/editor-ui/src/components/canvas/experimental/components/ExperimentalCanvasNodeSettings.vue b/packages/frontend/editor-ui/src/components/canvas/experimental/components/ExperimentalCanvasNodeSettings.vue index 47a35ef40e..7476ae5552 100644 --- a/packages/frontend/editor-ui/src/components/canvas/experimental/components/ExperimentalCanvasNodeSettings.vue +++ b/packages/frontend/editor-ui/src/components/canvas/experimental/components/ExperimentalCanvasNodeSettings.vue @@ -6,10 +6,11 @@ import { useWorkflowsStore } from '@/stores/workflows.store'; import { createEventBus } from '@n8n/utils/event-bus'; import { computed } from 'vue'; -const { nodeId, noWheel, isReadOnly } = defineProps<{ +const { nodeId, noWheel, isReadOnly, subTitle } = defineProps<{ nodeId: string; noWheel?: boolean; isReadOnly?: boolean; + subTitle?: string; }>(); defineSlots<{ actions?: {} }>(); @@ -40,6 +41,7 @@ function handleValueChanged(parameterData: IUpdateInformation) { :input-size="0" is-embedded-in-canvas :no-wheel="noWheel" + :sub-title="subTitle" @value-changed="handleValueChanged" >