feat(editor): Update Focus Panel design (no-changelog) (#17373)

This commit is contained in:
Daria
2025-07-17 17:07:10 +03:00
committed by GitHub
parent d36abb5a3a
commit ccac8f7d71
4 changed files with 94 additions and 40 deletions

View File

@@ -129,6 +129,7 @@ import IconLucideMousePointer from '~icons/lucide/mouse-pointer';
import IconLucideNetwork from '~icons/lucide/network';
import IconLucidePackageOpen from '~icons/lucide/package-open';
import IconLucidePalette from '~icons/lucide/palette';
import IconLucidePanelRight from '~icons/lucide/panel-right';
import IconLucidePause from '~icons/lucide/pause';
import IconLucidePen from '~icons/lucide/pen';
import IconLucidePencil from '~icons/lucide/pencil';
@@ -524,6 +525,7 @@ export const updatedIconSet = {
network: IconLucideNetwork,
'package-open': IconLucidePackageOpen,
palette: IconLucidePalette,
'panel-right': IconLucidePanelRight,
pause: IconLucidePause,
pen: IconLucidePen,
pencil: IconLucidePencil,

View File

@@ -1497,8 +1497,8 @@
"nodeView.couldntImportWorkflow": "Could not import workflow",
"nodeView.couldntLoadWorkflow.invalidWorkflowObject": "Invalid workflow object",
"nodeView.deletesTheCurrentExecutionData": "Deletes the current execution data",
"nodeView.focusPanel.title": "Focus",
"nodeView.focusPanel.noParameters": "No parameters focused. Focus a parameter by clicking on the action dropdown in the node detail view.",
"nodeView.focusPanel.noParameters.title": "Show a node parameter here, to iterate easily",
"nodeView.focusPanel.noParameters.subtitle": "For example, keep your prompt always visible so you can run the workflow while tweaking it",
"nodeView.focusPanel.missingParameter": "This parameter is no longer visible on the node. A related parameter was likely changed, removing this one.",
"nodeView.itLooksLikeYouHaveBeenEditingSomething": "It looks like you made some edits. If you leave before saving, your changes will be lost.",
"nodeView.loadingTemplate": "Loading template",

View File

@@ -314,14 +314,6 @@ const onResizeThrottle = useThrottleFn(onResize, 10);
@resize="onResizeThrottle"
>
<div :class="$style.container">
<div :class="$style.header">
<N8nText size="small" :bold="true">
{{ locale.baseText('nodeView.focusPanel.title') }}
</N8nText>
<div :class="$style.closeButton" @click="focusPanelStore.closeFocusPanel">
<n8n-icon icon="arrow-right" color="text-base" />
</div>
</div>
<div v-if="resolvedParameter" :class="$style.content">
<div :class="$style.tabHeader">
<div :class="$style.tabHeaderText">
@@ -330,17 +322,26 @@ const onResizeThrottle = useThrottleFn(onResize, 10);
</N8nText>
<N8nText color="text-base" size="xsmall">{{ resolvedParameter.node.name }}</N8nText>
</div>
<NodeExecuteButton
data-test-id="node-execute-button"
:node-name="resolvedParameter.node.name"
:tooltip="`Execute ${resolvedParameter.node.name}`"
:disabled="!isExecutable"
size="small"
icon="play"
:square="true"
:hide-label="true"
telemetry-source="focus"
></NodeExecuteButton>
<div :class="$style.buttonWrapper">
<NodeExecuteButton
data-test-id="node-execute-button"
:node-name="resolvedParameter.node.name"
:tooltip="`Execute ${resolvedParameter.node.name}`"
:disabled="!isExecutable"
size="small"
icon="play"
:square="true"
:hide-label="true"
telemetry-source="focus"
></NodeExecuteButton>
<N8nIcon
:class="$style.closeButton"
icon="x"
color="text-base"
size="xlarge"
@click="focusPanelStore.closeFocusPanel"
/>
</div>
</div>
<div :class="$style.parameterDetailsWrapper">
<div :class="$style.parameterOptionsWrapper">
@@ -448,8 +449,32 @@ const onResizeThrottle = useThrottleFn(onResize, 10);
</div>
<div v-else :class="[$style.content, $style.emptyContent]">
<div :class="$style.emptyText">
<N8nText color="text-base">
{{ locale.baseText('nodeView.focusPanel.noParameters') }}
<div :class="$style.focusParameterWrapper">
<div :class="$style.iconWrapper">
<N8nIcon :class="$style.forceHover" icon="panel-right" size="medium" />
<N8nIcon
:class="$style.pointerIcon"
icon="mouse-pointer"
color="text-dark"
size="large"
/>
</div>
<N8nIcon icon="ellipsis-vertical" size="small" color="text-base" />
<N8nRadioButtons
size="small"
:model-value="'expression'"
:disabled="true"
:options="[
{ label: locale.baseText('parameterInput.fixed'), value: 'fixed' },
{ label: locale.baseText('parameterInput.expression'), value: 'expression' },
]"
/>
</div>
<N8nText color="text-base" size="medium" :bold="true">
{{ locale.baseText('nodeView.focusPanel.noParameters.title') }}
</N8nText>
<N8nText color="text-base" size="small">
{{ locale.baseText('nodeView.focusPanel.noParameters.subtitle') }}
</N8nText>
</div>
</div>
@@ -463,7 +488,7 @@ const onResizeThrottle = useThrottleFn(onResize, 10);
display: flex;
flex-direction: row nowrap;
border-left: 1px solid var(--color-foreground-base);
background: var(--color-foreground-light);
background: var(--color-background-xlight);
overflow-y: hidden;
height: 100%;
}
@@ -474,18 +499,6 @@ const onResizeThrottle = useThrottleFn(onResize, 10);
height: 100%;
}
.closeButton:hover {
cursor: pointer;
}
.header {
display: flex;
padding: var(--spacing-2xs);
justify-content: space-between;
border-bottom: 1px solid var(--color-foreground-base);
background: var(--color-foreground-xlight);
}
.content {
display: flex;
flex-direction: column;
@@ -498,7 +511,35 @@ const onResizeThrottle = useThrottleFn(onResize, 10);
align-items: center;
.emptyText {
max-width: 300px;
margin: 0 var(--spacing-xl);
display: flex;
flex-direction: column;
gap: var(--spacing-2xs);
.focusParameterWrapper {
display: flex;
align-items: center;
justify-content: center;
gap: var(--spacing-2xs);
margin-bottom: var(--spacing-m);
.iconWrapper {
position: relative;
display: inline-block;
}
.pointerIcon {
position: absolute;
top: 100%;
left: 50%;
transform: translate(-20%, -30%);
pointer-events: none;
}
:global([class*='_disabled_']) {
cursor: default !important;
}
}
}
}
@@ -517,8 +558,8 @@ const onResizeThrottle = useThrottleFn(onResize, 10);
.buttonWrapper {
display: flex;
padding: 6px 8px 6px 34px;
justify-content: flex-end;
gap: var(--spacing-2xs);
align-items: center;
}
}
@@ -545,6 +586,7 @@ const onResizeThrottle = useThrottleFn(onResize, 10);
font-size: var(--font-size-2xs);
:global(.cm-editor) {
background-color: var(--color-code-background);
width: 100%;
}
}
@@ -552,7 +594,17 @@ const onResizeThrottle = useThrottleFn(onResize, 10);
}
}
.closeButton {
cursor: pointer;
}
.heightFull {
height: 100%;
}
.forceHover {
color: var(--color-button-secondary-hover-active-focus-font);
border-color: var(--color-button-secondary-hover-active-focus-border);
background-color: var(--color-button-secondary-hover-active-focus-background);
}
</style>

View File

@@ -135,7 +135,7 @@ function onAskAssistantButtonClick() {
<n8n-icon-button
type="tertiary"
size="large"
icon="list"
icon="panel-right"
@click="focusPanelStore.toggleFocusPanel"
/>
</KeyboardShortcutTooltip>