diff --git a/browser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-dragging-link-chromium-linux.png b/browser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-dragging-link-chromium-linux.png
index df8f56cb42..e9a11910a2 100644
Binary files a/browser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-dragging-link-chromium-linux.png and b/browser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-dragging-link-chromium-linux.png differ
diff --git a/browser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-input-drag-ctrl-alt-chromium-linux.png b/browser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-input-drag-ctrl-alt-chromium-linux.png
index ebfe67a8de..66b808e342 100644
Binary files a/browser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-input-drag-ctrl-alt-chromium-linux.png and b/browser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-input-drag-ctrl-alt-chromium-linux.png differ
diff --git a/browser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-input-drag-reuses-origin-chromium-linux.png b/browser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-input-drag-reuses-origin-chromium-linux.png
index cbbb023308..5fa283cee0 100644
Binary files a/browser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-input-drag-reuses-origin-chromium-linux.png and b/browser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-input-drag-reuses-origin-chromium-linux.png differ
diff --git a/browser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-reroute-input-drag-chromium-linux.png b/browser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-reroute-input-drag-chromium-linux.png
index 38d93e7178..5c08aded80 100644
Binary files a/browser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-reroute-input-drag-chromium-linux.png and b/browser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-reroute-input-drag-chromium-linux.png differ
diff --git a/browser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-reroute-output-shift-drag-chromium-linux.png b/browser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-reroute-output-shift-drag-chromium-linux.png
index 9740334b8e..76946cbc04 100644
Binary files a/browser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-reroute-output-shift-drag-chromium-linux.png and b/browser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-reroute-output-shift-drag-chromium-linux.png differ
diff --git a/browser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-shift-output-multi-link-chromium-linux.png b/browser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-shift-output-multi-link-chromium-linux.png
index 5df3a9f421..6a39534a22 100644
Binary files a/browser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-shift-output-multi-link-chromium-linux.png and b/browser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-shift-output-multi-link-chromium-linux.png differ
diff --git a/browser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-snap-to-node-chromium-linux.png b/browser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-snap-to-node-chromium-linux.png
index c8d2db1f44..0b51591e7c 100644
Binary files a/browser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-snap-to-node-chromium-linux.png and b/browser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-snap-to-node-chromium-linux.png differ
diff --git a/browser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-snap-to-slot-chromium-linux.png b/browser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-snap-to-slot-chromium-linux.png
index ead82b036d..a12651973e 100644
Binary files a/browser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-snap-to-slot-chromium-linux.png and b/browser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-snap-to-slot-chromium-linux.png differ
diff --git a/browser_tests/tests/vueNodes/widgets/load/uploadWidgets.spec.ts-snapshots/vue-nodes-upload-widgets-chromium-linux.png b/browser_tests/tests/vueNodes/widgets/load/uploadWidgets.spec.ts-snapshots/vue-nodes-upload-widgets-chromium-linux.png
index ec764bd4bb..8318ff97bc 100644
Binary files a/browser_tests/tests/vueNodes/widgets/load/uploadWidgets.spec.ts-snapshots/vue-nodes-upload-widgets-chromium-linux.png and b/browser_tests/tests/vueNodes/widgets/load/uploadWidgets.spec.ts-snapshots/vue-nodes-upload-widgets-chromium-linux.png differ
diff --git a/src/renderer/extensions/vueNodes/components/LGraphNode.vue b/src/renderer/extensions/vueNodes/components/LGraphNode.vue
index a3ed81cb57..72d0641345 100644
--- a/src/renderer/extensions/vueNodes/components/LGraphNode.vue
+++ b/src/renderer/extensions/vueNodes/components/LGraphNode.vue
@@ -8,8 +8,9 @@
:data-node-id="nodeData.id"
:class="
cn(
- 'bg-node-component-surface',
- 'lg-node absolute rounded-2xl touch-none flex flex-col',
+ 'bg-node-component-surface lg-node absolute',
+ 'min-h-min min-w-min contain-style contain-layout',
+ 'rounded-2xl touch-none flex flex-col',
'border-1 border-solid border-node-component-border',
// hover (only when node should handle events)
shouldHandleNodePointerEvents &&
@@ -83,7 +84,7 @@
@@ -150,7 +151,6 @@ import { cn } from '@/utils/tailwindUtil'
import type { ResizeHandleDirection } from '../interactions/resize/resizeMath'
import { useNodeResize } from '../interactions/resize/useNodeResize'
-import { calculateIntrinsicSize } from '../utils/calculateIntrinsicSize'
import LivePreview from './LivePreview.vue'
import NodeContent from './NodeContent.vue'
import NodeHeader from './NodeHeader.vue'
@@ -269,18 +269,9 @@ const handleContextMenu = (event: MouseEvent) => {
onMounted(() => {
// Set initial DOM size from layout store, but respect intrinsic content minimum
- if (size.value && nodeContainerRef.value && transformState) {
- const intrinsicMin = calculateIntrinsicSize(
- nodeContainerRef.value,
- transformState.camera.z
- )
-
- // Use the larger of stored size or intrinsic minimum
- const finalWidth = Math.max(size.value.width, intrinsicMin.width)
- const finalHeight = Math.max(size.value.height, intrinsicMin.height)
-
- nodeContainerRef.value.style.width = `${finalWidth}px`
- nodeContainerRef.value.style.height = `${finalHeight}px`
+ if (size.value && nodeContainerRef.value) {
+ nodeContainerRef.value.style.width = `${size.value.width}px`
+ nodeContainerRef.value.style.height = `${size.value.height}px`
}
})
diff --git a/src/renderer/extensions/vueNodes/components/NodeHeader.vue b/src/renderer/extensions/vueNodes/components/NodeHeader.vue
index efee5b1c17..decfd63f0b 100644
--- a/src/renderer/extensions/vueNodes/components/NodeHeader.vue
+++ b/src/renderer/extensions/vueNodes/components/NodeHeader.vue
@@ -6,7 +6,8 @@
v-else
:class="
cn(
- 'lg-node-header p-4 rounded-t-2xl w-full bg-node-component-header-surface text-node-component-header',
+ 'lg-node-header p-4 rounded-t-2xl w-full min-w-50',
+ 'bg-node-component-header-surface text-node-component-header',
collapsed && 'rounded-2xl'
)
"
diff --git a/src/renderer/extensions/vueNodes/interactions/resize/resizeMath.ts b/src/renderer/extensions/vueNodes/interactions/resize/resizeMath.ts
index c58b0db6f8..a837d59c58 100644
--- a/src/renderer/extensions/vueNodes/interactions/resize/resizeMath.ts
+++ b/src/renderer/extensions/vueNodes/interactions/resize/resizeMath.ts
@@ -19,26 +19,6 @@ function applyHandleDelta(
}
}
-function clampToMinSize(size: Size, minSize: Size): Size {
- return {
- width: Math.max(size.width, minSize.width),
- height: Math.max(size.height, minSize.height)
- }
-}
-
-function snapSize(
- size: Size,
- minSize: Size,
- snapFn?: (size: Size) => Size
-): Size {
- if (!snapFn) return size
- const snapped = snapFn(size)
- return {
- width: Math.max(minSize.width, snapped.width),
- height: Math.max(minSize.height, snapped.height)
- }
-}
-
function computeAdjustedPosition(
startPosition: Point,
startSize: Size,
@@ -68,20 +48,17 @@ export function computeResizeOutcome({
startSize,
startPosition,
delta,
- minSize,
handle,
snapFn
}: {
startSize: Size
startPosition: Point
delta: Point
- minSize: Size
handle: ResizeHandleDirection
snapFn?: (size: Size) => Size
}): { size: Size; position: Point } {
const resized = applyHandleDelta(startSize, delta, handle)
- const clamped = clampToMinSize(resized, minSize)
- const snapped = snapSize(clamped, minSize, snapFn)
+ const snapped = snapFn?.(resized) ?? resized
const position = computeAdjustedPosition(
startPosition,
startSize,
@@ -98,19 +75,16 @@ export function computeResizeOutcome({
export function createResizeSession(config: {
startSize: Size
startPosition: Point
- minSize: Size
handle: ResizeHandleDirection
}) {
const startSize = { ...config.startSize }
const startPosition = { ...config.startPosition }
- const minSize = { ...config.minSize }
const handle = config.handle
return (delta: Point, snapFn?: (size: Size) => Size) =>
computeResizeOutcome({
startSize,
startPosition,
- minSize,
handle,
delta,
snapFn
diff --git a/src/renderer/extensions/vueNodes/interactions/resize/useNodeResize.ts b/src/renderer/extensions/vueNodes/interactions/resize/useNodeResize.ts
index 2566fe41b6..39d745073c 100644
--- a/src/renderer/extensions/vueNodes/interactions/resize/useNodeResize.ts
+++ b/src/renderer/extensions/vueNodes/interactions/resize/useNodeResize.ts
@@ -5,7 +5,6 @@ import type { TransformState } from '@/renderer/core/layout/injectionKeys'
import type { Point, Size } from '@/renderer/core/layout/types'
import { useNodeSnap } from '@/renderer/extensions/vueNodes/composables/useNodeSnap'
import { useShiftKeySync } from '@/renderer/extensions/vueNodes/composables/useShiftKeySync'
-import { calculateIntrinsicSize } from '@/renderer/extensions/vueNodes/utils/calculateIntrinsicSize'
import type { ResizeHandleDirection } from './resizeMath'
import { createResizeSession, toCanvasDelta } from './resizeMath'
@@ -76,8 +75,6 @@ export function useNodeResize(
height: rect.height / scale
}
- const minSize = calculateIntrinsicSize(nodeElement, scale)
-
// Track shift key state and sync to canvas for snap preview
const stopShiftSync = trackShiftKey(event)
@@ -89,7 +86,6 @@ export function useNodeResize(
resizeSession.value = createResizeSession({
startSize,
startPosition: { ...startPosition },
- minSize,
handle
})
diff --git a/src/renderer/extensions/vueNodes/utils/calculateIntrinsicSize.test.ts b/src/renderer/extensions/vueNodes/utils/calculateIntrinsicSize.test.ts
deleted file mode 100644
index cd34f8a3fb..0000000000
--- a/src/renderer/extensions/vueNodes/utils/calculateIntrinsicSize.test.ts
+++ /dev/null
@@ -1,138 +0,0 @@
-import { afterEach, beforeEach, describe, expect, it } from 'vitest'
-
-import { calculateIntrinsicSize } from './calculateIntrinsicSize'
-
-describe('calculateIntrinsicSize', () => {
- let element: HTMLElement
-
- beforeEach(() => {
- // Create a test element
- element = document.createElement('div')
- element.style.width = '200px'
- element.style.height = '100px'
- document.body.appendChild(element)
- })
-
- afterEach(() => {
- document.body.removeChild(element)
- })
-
- it('should calculate intrinsic size and convert to canvas coordinates', () => {
- // Mock getBoundingClientRect to return specific dimensions
- const originalGetBoundingClientRect = element.getBoundingClientRect
- element.getBoundingClientRect = () => ({
- width: 300,
- height: 150,
- top: 0,
- left: 0,
- bottom: 150,
- right: 300,
- x: 0,
- y: 0,
- toJSON: () => ({})
- })
-
- const scale = 2
- const result = calculateIntrinsicSize(element, scale)
-
- // Should divide by scale to convert from screen to canvas coordinates
- expect(result).toEqual({
- width: 150, // 300 / 2
- height: 75 // 150 / 2
- })
-
- element.getBoundingClientRect = originalGetBoundingClientRect
- })
-
- it('should restore original size after measuring', () => {
- const originalWidth = element.style.width
- const originalHeight = element.style.height
-
- element.getBoundingClientRect = () => ({
- width: 300,
- height: 150,
- top: 0,
- left: 0,
- bottom: 150,
- right: 300,
- x: 0,
- y: 0,
- toJSON: () => ({})
- })
-
- calculateIntrinsicSize(element, 1)
-
- // Should restore original styles
- expect(element.style.width).toBe(originalWidth)
- expect(element.style.height).toBe(originalHeight)
- })
-
- it('should handle scale of 1 correctly', () => {
- element.getBoundingClientRect = () => ({
- width: 400,
- height: 200,
- top: 0,
- left: 0,
- bottom: 200,
- right: 400,
- x: 0,
- y: 0,
- toJSON: () => ({})
- })
-
- const result = calculateIntrinsicSize(element, 1)
-
- expect(result).toEqual({
- width: 400,
- height: 200
- })
- })
-
- it('should handle fractional scales', () => {
- element.getBoundingClientRect = () => ({
- width: 300,
- height: 150,
- top: 0,
- left: 0,
- bottom: 150,
- right: 300,
- x: 0,
- y: 0,
- toJSON: () => ({})
- })
-
- const result = calculateIntrinsicSize(element, 0.5)
-
- expect(result).toEqual({
- width: 600, // 300 / 0.5
- height: 300 // 150 / 0.5
- })
- })
-
- it('should temporarily set width and height to auto during measurement', () => {
- let widthDuringMeasurement = ''
- let heightDuringMeasurement = ''
-
- element.getBoundingClientRect = function (this: HTMLElement) {
- widthDuringMeasurement = this.style.width
- heightDuringMeasurement = this.style.height
- return {
- width: 300,
- height: 150,
- top: 0,
- left: 0,
- bottom: 150,
- right: 300,
- x: 0,
- y: 0,
- toJSON: () => ({})
- }
- }
-
- calculateIntrinsicSize(element, 1)
-
- // During measurement, styles should be set to 'auto'
- expect(widthDuringMeasurement).toBe('auto')
- expect(heightDuringMeasurement).toBe('auto')
- })
-})
diff --git a/src/renderer/extensions/vueNodes/utils/calculateIntrinsicSize.ts b/src/renderer/extensions/vueNodes/utils/calculateIntrinsicSize.ts
deleted file mode 100644
index 36da7cd827..0000000000
--- a/src/renderer/extensions/vueNodes/utils/calculateIntrinsicSize.ts
+++ /dev/null
@@ -1,34 +0,0 @@
-/**
- * Calculate the intrinsic (minimum content-based) size of a node element
- *
- * Temporarily sets the element to auto-size to measure its natural content dimensions,
- * then converts from screen coordinates to canvas coordinates using the camera scale.
- *
- * @param element - The node element to measure
- * @param scale - Camera zoom scale for coordinate conversion
- * @returns The intrinsic minimum size in canvas coordinates
- */
-export function calculateIntrinsicSize(
- element: HTMLElement,
- scale: number
-): { width: number; height: number } {
- // Store original size to restore later
- const originalWidth = element.style.width
- const originalHeight = element.style.height
-
- // Temporarily set to auto to measure natural content size
- element.style.width = 'auto'
- element.style.height = 'auto'
-
- const intrinsicRect = element.getBoundingClientRect()
-
- // Restore original size
- element.style.width = originalWidth
- element.style.height = originalHeight
-
- // Convert from screen coordinates to canvas coordinates
- return {
- width: intrinsicRect.width / scale,
- height: intrinsicRect.height / scale
- }
-}
diff --git a/src/renderer/extensions/vueNodes/widgets/components/layout/WidgetLayoutField.vue b/src/renderer/extensions/vueNodes/widgets/components/layout/WidgetLayoutField.vue
index e596ba290e..24411c9cc0 100644
--- a/src/renderer/extensions/vueNodes/widgets/components/layout/WidgetLayoutField.vue
+++ b/src/renderer/extensions/vueNodes/widgets/components/layout/WidgetLayoutField.vue
@@ -12,20 +12,20 @@ defineProps<{