Skip to main content
The NodeResizer component adds interactive resize handles to nodes, allowing users to dynamically change node dimensions.

Installation

npm install @vue-flow/node-resizer

Basic Usage

<script setup>
import { NodeResizer } from '@vue-flow/node-resizer'
</script>

<template>
  <div class="custom-node">
    <NodeResizer />
    <div>Resizable Node Content</div>
  </div>
</template>

<style>
@import '@vue-flow/node-resizer/dist/style.css';
</style>

Props

Target Node

nodeId
string
ID of the node to resize. If not provided, uses the node ID from context (when used inside a custom node component).

Visibility

isVisible
boolean
default:"true"
Show or hide the resize controls.
<NodeResizer :is-visible="node.selected" />

Dimensions

minWidth
number
Minimum width the node can be resized to.
minHeight
number
Minimum height the node can be resized to.
maxWidth
number
Maximum width the node can be resized to.
maxHeight
number
Maximum height the node can be resized to.

Aspect Ratio

keepAspectRatio
boolean | number
Maintain aspect ratio during resize.
  • true: Keep original aspect ratio
  • false: Free resize
  • number: Use specific aspect ratio (e.g., 1.5 for 3:2 ratio)

Appearance

color
string
Color of the resize handles and lines.
<NodeResizer color="#3b82f6" />
handleClassName
string
CSS class for corner resize handles.
handleStyle
CSSProperties
Inline styles for corner resize handles.
lineClassName
string
CSS class for edge resize lines.
lineStyle
CSSProperties
Inline styles for edge resize lines.

Behavior

shouldResize
ShouldResize
Function to determine if resize should occur. Receives the drag event and resize parameters.
<NodeResizer :should-resize="shouldResize" />
function shouldResize(event, params) {
  // Only allow resize if width > 100
  return params.width > 100
}
autoScale
boolean
default:"true"
Scale the resize controls with the viewport zoom level.

Events

@resizeStart
(event: OnResizeStart) => void
Fired when resizing starts.
interface OnResizeStart {
  event: ResizeDragEvent
  params: ResizeParams
}

interface ResizeParams {
  x: number
  y: number
  width: number
  height: number
}
@resize
(event: OnResize) => void
Fired during resizing.
interface OnResize {
  event: ResizeDragEvent
  params: ResizeParamsWithDirection
}

interface ResizeParamsWithDirection extends ResizeParams {
  direction: number[] // [x, y] direction vector
}
@resizeEnd
(event: OnResizeEnd) => void
Fired when resizing ends.

Examples

Basic Resizable Node

<script setup>
import { NodeResizer } from '@vue-flow/node-resizer'
</script>

<template>
  <div class="custom-node">
    <NodeResizer 
      :min-width="100" 
      :min-height="50" 
    />
    <div class="content">
      Resize me!
    </div>
  </div>
</template>

Show Only When Selected

<script setup>
import { NodeResizer } from '@vue-flow/node-resizer'
import { inject } from 'vue'

const node = inject('node')
</script>

<template>
  <div class="custom-node">
    <NodeResizer :is-visible="node.selected" />
    <div>Content</div>
  </div>
</template>

Constrained Dimensions

<template>
  <div class="custom-node">
    <NodeResizer 
      :min-width="200" 
      :min-height="100" 
      :max-width="800" 
      :max-height="600" 
    />
    <div>Constrained resize</div>
  </div>
</template>

Maintain Aspect Ratio

<template>
  <div class="custom-node">
    <!-- Keep original aspect ratio -->
    <NodeResizer :keep-aspect-ratio="true" />
    
    <!-- Use 16:9 aspect ratio -->
    <!-- <NodeResizer :keep-aspect-ratio="16/9" /> -->
    
    <div>Square content</div>
  </div>
</template>

Custom Colors

<template>
  <div class="custom-node">
    <NodeResizer color="#3b82f6" />
    <div>Blue handles</div>
  </div>
</template>

Custom Handle Styles

<template>
  <div class="custom-node">
    <NodeResizer 
      :handle-style="{ 
        width: '12px', 
        height: '12px', 
        borderRadius: '50%',
        background: '#3b82f6'
      }"
      :line-style="{ 
        borderColor: '#3b82f6',
        borderWidth: '2px' 
      }"
    />
    <div>Custom styled handles</div>
  </div>
</template>

Event Handling

<script setup>
import { NodeResizer } from '@vue-flow/node-resizer'

function onResizeStart({ params }) {
  console.log('Start resize:', params)
}

function onResize({ params }) {
  console.log('Resizing:', params.width, params.height)
}

function onResizeEnd({ params }) {
  console.log('End resize:', params)
}
</script>

<template>
  <div class="custom-node">
    <NodeResizer 
      @resize-start="onResizeStart"
      @resize="onResize"
      @resize-end="onResizeEnd"
    />
    <div>Content</div>
  </div>
</template>

Conditional Resize

<script setup>
import { NodeResizer } from '@vue-flow/node-resizer'

function shouldResize(event, params) {
  // Only allow resize if dimensions are reasonable
  if (params.width < 50 || params.height < 50) {
    return false
  }
  
  // Don't resize on Shift key
  if (event.sourceEvent?.shiftKey) {
    return false
  }
  
  return true
}
</script>

<template>
  <div class="custom-node">
    <NodeResizer :should-resize="shouldResize" />
    <div>Conditional resize</div>
  </div>
</template>

Without Auto-scaling

<template>
  <div class="custom-node">
    <!-- Handles won't scale with zoom -->
    <NodeResizer :auto-scale="false" />
    <div>Fixed size handles</div>
  </div>
</template>

Complete Custom Node Example

<script setup>
import { NodeResizer } from '@vue-flow/node-resizer'
import { Handle, Position } from '@vue-flow/core'
import { inject } from 'vue'

const node = inject('node')
</script>

<template>
  <div class="resizable-node">
    <NodeResizer 
      :is-visible="node.selected"
      :min-width="150"
      :min-height="100"
      color="#3b82f6"
    />
    
    <Handle type="target" :position="Position.Left" />
    
    <div class="node-content">
      <h3>{{ node.label }}</h3>
      <p>{{ node.data?.description }}</p>
    </div>
    
    <Handle type="source" :position="Position.Right" />
  </div>
</template>

<style scoped>
.resizable-node {
  padding: 20px;
  border: 2px solid #3b82f6;
  border-radius: 8px;
  background: white;
}

.node-content {
  min-width: 150px;
}
</style>

Styling

/* Resize handle (corners) */
.vue-flow__resize-control.handle {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: #3b82f6;
  border: 2px solid white;
}

/* Resize line (edges) */
.vue-flow__resize-control.line {
  border-color: #3b82f6;
  border-width: 2px;
}

/* Hover states */
.vue-flow__resize-control.handle:hover {
  background: #2563eb;
}
The NodeResizer must be used inside a custom node component. It automatically detects the parent node’s ID from context, but you can override it with the nodeId prop.

Build docs developers (and LLMs) love