From 54f13930a4223844a46d378fac6e7c8a92c7dbb0 Mon Sep 17 00:00:00 2001 From: Christian Byrne Date: Sun, 22 Feb 2026 01:03:15 -0800 Subject: [PATCH] feat: add display name mappings for Essentials tab nodes (#9072) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary Add frontend-only display name mappings for nodes shown in the Essentials tab, plus parse the new `essentials_category` field from the backend. ## Changes - **What**: Created `src/constants/essentialsDisplayNames.ts` with a static mapping of node names to user-friendly display names (e.g. `CLIPTextEncode` → "Text", `ImageScale` → "Resize Image"). Regular nodes use exact name matching; blueprint nodes use prefix matching since their filenames include model-specific suffixes. Integrated into `NodeLibrarySidebarTab.vue`'s `renderedRoot` computed for leaf node labels with fallback to `display_name`. Added `essentials_category` (z.string().optional()) to the node def schema and `ComfyNodeDefImpl` to parse the field already sent by the backend (PR #12357). ## Review Focus Display names are resolved only in the Essentials tab tree view (`NodeLibrarySidebarTab.vue`), not globally, to avoid side effects on search, bookmarks, or other views. Blueprint prefix matching is ordered longest-first so more specific prefixes (e.g. `image_inpainting_`) match before shorter ones (e.g. `image_edit`). ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-9072-feat-add-display-name-mappings-for-Essentials-tab-nodes-30f6d73d3650817c9acdc9b0315ed0be) by [Unito](https://www.unito.io) --- .../sidebar/tabs/NodeLibrarySidebarTab.vue | 5 +- .../sidebar/tabs/NodeLibrarySidebarTabV2.vue | 16 ++- .../nodeLibrary/EssentialNodeCard.test.ts | 2 +- .../tabs/nodeLibrary/EssentialNodeCard.vue | 4 +- src/constants/essentialsDisplayNames.test.ts | 105 +++++++++++++++++ src/constants/essentialsDisplayNames.ts | 108 ++++++++++++++++++ src/locales/en/main.json | 38 ++++++ 7 files changed, 270 insertions(+), 8 deletions(-) create mode 100644 src/constants/essentialsDisplayNames.test.ts create mode 100644 src/constants/essentialsDisplayNames.ts diff --git a/src/components/sidebar/tabs/NodeLibrarySidebarTab.vue b/src/components/sidebar/tabs/NodeLibrarySidebarTab.vue index b34949602..061f92a2c 100644 --- a/src/components/sidebar/tabs/NodeLibrarySidebarTab.vue +++ b/src/components/sidebar/tabs/NodeLibrarySidebarTab.vue @@ -154,6 +154,7 @@ import { render } from 'vue' +import { resolveEssentialsDisplayName } from '@/constants/essentialsDisplayNames' import SearchBox from '@/components/common/SearchBox.vue' import type { SearchFilter } from '@/components/common/SearchFilterChip.vue' import TreeExplorer from '@/components/common/TreeExplorer.vue' @@ -276,7 +277,9 @@ const renderedRoot = computed>(() => { return { key: node.key, - label: node.leaf ? node.data.display_name : node.label, + label: node.leaf + ? (resolveEssentialsDisplayName(node.data) ?? node.data.display_name) + : node.label, leaf: node.leaf, data: node.data, getIcon() { diff --git a/src/components/sidebar/tabs/NodeLibrarySidebarTabV2.vue b/src/components/sidebar/tabs/NodeLibrarySidebarTabV2.vue index a86947df6..91556fac0 100644 --- a/src/components/sidebar/tabs/NodeLibrarySidebarTabV2.vue +++ b/src/components/sidebar/tabs/NodeLibrarySidebarTabV2.vue @@ -114,6 +114,7 @@ import { import { computed, nextTick, onMounted, ref, watchEffect } from 'vue' import { useI18n } from 'vue-i18n' +import { resolveEssentialsDisplayName } from '@/constants/essentialsDisplayNames' import SearchBox from '@/components/common/SearchBoxV2.vue' import { useFeatureFlags } from '@/composables/useFeatureFlags' import { useNodeDragToCanvas } from '@/composables/node/useNodeDragToCanvas' @@ -230,16 +231,23 @@ function findFirstLeaf(node: TreeNode): TreeNode | undefined { } function fillNodeInfo( - node: TreeNode + node: TreeNode, + { useEssentialsLabels = false }: { useEssentialsLabels?: boolean } = {} ): RenderedTreeExplorerNode { - const children = node.children?.map(fillNodeInfo) + const children = node.children?.map((child) => + fillNodeInfo(child, { useEssentialsLabels }) + ) const totalLeaves = node.leaf ? 1 : (children?.reduce((acc, child) => acc + child.totalLeaves, 0) ?? 0) return { key: node.key, - label: node.leaf ? node.data?.display_name : node.label, + label: node.leaf + ? useEssentialsLabels + ? (resolveEssentialsDisplayName(node.data) ?? node.data?.display_name) + : node.data?.display_name + : node.label, leaf: node.leaf, data: node.data, icon: node.leaf ? 'icon-[comfy--node]' : getFolderIcon(node), @@ -274,7 +282,7 @@ const essentialSections = computed(() => { const renderedEssentialRoot = computed(() => { const section = essentialSections.value[0] return section - ? fillNodeInfo(applySorting(section.tree)) + ? fillNodeInfo(applySorting(section.tree), { useEssentialsLabels: true }) : fillNodeInfo({ key: 'root', label: '', children: [] }) }) diff --git a/src/components/sidebar/tabs/nodeLibrary/EssentialNodeCard.test.ts b/src/components/sidebar/tabs/nodeLibrary/EssentialNodeCard.test.ts index 4497ef59f..f34d84a4b 100644 --- a/src/components/sidebar/tabs/nodeLibrary/EssentialNodeCard.test.ts +++ b/src/components/sidebar/tabs/nodeLibrary/EssentialNodeCard.test.ts @@ -44,7 +44,7 @@ describe('EssentialNodeCard', () => { return { key: 'test-key', - label: 'Test Node', + label: data.display_name, icon: 'icon-[comfy--node]', type: 'node', totalLeaves: 1, diff --git a/src/components/sidebar/tabs/nodeLibrary/EssentialNodeCard.vue b/src/components/sidebar/tabs/nodeLibrary/EssentialNodeCard.vue index 9a5b7edd6..c2003ef15 100644 --- a/src/components/sidebar/tabs/nodeLibrary/EssentialNodeCard.vue +++ b/src/components/sidebar/tabs/nodeLibrary/EssentialNodeCard.vue @@ -1,7 +1,7 @@