Add support for NO_TITLE in vue, disabling border (#7589)

When `node.title_mode` is set to `TitleMode.NO_TITLE` the node header is
not displayed in vue mode.
| Before | After |
| ------ | ----- |
| <img width="360" alt="before"
src="https://github.com/user-attachments/assets/0e64c3df-8bcb-496f-a53c-618fdca79610"/>
| <img width="360" alt="after"
src="https://github.com/user-attachments/assets/34ea3a28-cc2e-4316-a154-40f54bdf8e60"
/>|

When a node has specified both `NO_TITLE` and a transparent background,
node borders are also disabled in vue mode.
| Before | After |
| ------ | ----- |
| <img width="360" alt="before"
src="https://github.com/user-attachments/assets/e52cf371-ba7e-401c-b9e5-b53607c26778"/>
| <img width="360" alt="after"
src="https://github.com/user-attachments/assets/979a4ba4-cf6d-49b3-ae97-6e1d62f487cc"
/>|

Known issues:
- `NODE_TITLE_HEIGHT` strikes again.
<img width="254" height="64" alt="image"
src="https://github.com/user-attachments/assets/526b1e2c-66dd-4c5d-9954-8c997a0ab5b8"
/>

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-7589-Add-support-for-NO_TITLE-in-vue-disabling-border-2cc6d73d36508182834bc78ea8dffa27)
by [Unito](https://www.unito.io)
This commit is contained in:
AustinMroz
2025-12-20 13:32:07 -08:00
committed by GitHub
parent e5edbf91eb
commit 17be3b9770
3 changed files with 39 additions and 13 deletions

View File

@@ -31,8 +31,9 @@ import type {
LGraphTriggerAction,
LGraphTriggerEvent,
LGraphTriggerParam
} from '../../lib/litegraph/src/litegraph'
import { NodeSlotType } from '../../lib/litegraph/src/types/globalEnums'
} from '@/lib/litegraph/src/litegraph'
import type { TitleMode } from '@/lib/litegraph/src/types/globalEnums'
import { NodeSlotType } from '@/lib/litegraph/src/types/globalEnums'
export interface WidgetSlotMetadata {
index: number
@@ -55,26 +56,27 @@ export interface SafeWidgetData {
}
export interface VueNodeData {
executing: boolean
id: NodeId
title: string
type: string
mode: number
selected: boolean
executing: boolean
title: string
type: string
apiNode?: boolean
badges?: (LGraphBadge | (() => LGraphBadge))[]
subgraphId?: string | null
widgets?: SafeWidgetData[]
inputs?: INodeInputSlot[]
outputs?: INodeOutputSlot[]
hasErrors?: boolean
bgcolor?: string
color?: string
flags?: {
collapsed?: boolean
pinned?: boolean
}
color?: string
bgcolor?: string
hasErrors?: boolean
inputs?: INodeInputSlot[]
outputs?: INodeOutputSlot[]
shape?: number
subgraphId?: string | null
titleMode?: TitleMode
widgets?: SafeWidgetData[]
}
export interface GraphNodeManager {
@@ -262,6 +264,7 @@ export function useGraphNodeManager(graph: LGraph): GraphNodeManager {
title: typeof node.title === 'string' ? node.title : '',
type: nodeType,
mode: node.mode || 0,
titleMode: node.title_mode,
selected: node.selected || false,
executing: false, // Will be updated separately based on execution state
subgraphId,

View File

@@ -51,7 +51,10 @@
@dragleave="handleDragLeave"
@drop.stop.prevent="handleDrop"
>
<div class="flex flex-col justify-center items-center relative">
<div
v-if="displayHeader"
class="flex flex-col justify-center items-center relative"
>
<template v-if="isCollapsed">
<SlotConnectionDot
v-if="hasInputs"
@@ -145,6 +148,7 @@ import {
LiteGraph,
RenderShape
} from '@/lib/litegraph/src/litegraph'
import { TitleMode } from '@/lib/litegraph/src/types/globalEnums'
import { useSettingStore } from '@/platform/settings/settingStore'
import { useTelemetry } from '@/platform/telemetry'
import { useCanvasStore } from '@/renderer/core/canvas/canvasStore'
@@ -165,6 +169,7 @@ import { app } from '@/scripts/app'
import { useExecutionStore } from '@/stores/executionStore'
import { useNodeOutputStore } from '@/stores/imagePreviewStore'
import { useColorPaletteStore } from '@/stores/workspace/colorPaletteStore'
import { isTransparent } from '@/utils/colorUtil'
import {
getLocatorIdFromNodeData,
getNodeByLocatorId
@@ -215,6 +220,8 @@ const hasAnyError = computed((): boolean => {
)
})
const displayHeader = computed(() => nodeData.titleMode !== TitleMode.NO_TITLE)
const isCollapsed = computed(() => nodeData.flags?.collapsed ?? false)
const bypassed = computed(
(): boolean => nodeData.mode === LGraphEventMode.BYPASS
@@ -368,6 +375,13 @@ const { latestPreviewUrl, shouldShowPreviewImg } = useNodePreviewState(
const borderClass = computed(() => {
if (hasAnyError.value) return 'border-node-stroke-error'
//FIXME need a better way to detecting transparency
if (
!displayHeader.value &&
nodeData.bgcolor &&
isTransparent(nodeData.bgcolor)
)
return 'border-0'
return ''
})

View File

@@ -21,6 +21,15 @@ export interface ColorAdjustOptions {
opacity?: number
}
export function isTransparent(color: string) {
if (color === 'transparent') return true
if (color[0] === '#') {
if (color.length === 5) return color[4] === '0'
if (color.length === 9) return color.substring(7) === '00'
}
return false
}
function rgbToHsl({ r, g, b }: RGB): HSL {
r /= 255
g /= 255