<NodeResizer />
The <NodeResizer /> component can be used to add a resize functionality to your
nodes. It renders draggable controls around the node to resize in all directions.
import { memo } from 'react';
import { Handle, Position, NodeResizer } from '@xyflow/react';
const ResizableNode = ({ data }) => {
return (
<>
<NodeResizer minWidth={100} minHeight={30} />
<Handle type="target" position={Position.Left} />
<div style={{ padding: 10 }}>{data.label}</div>
<Handle type="source" position={Position.Right} />
</>
);
};
export default memo(ResizableNode);Props
For TypeScript users, the props type for the <NodeResizer /> component is exported
as NodeResizerProps.
nodeId?: stringId of the node it is resizing.color?: stringColor of the resize handle.handleClassName?: stringClass name applied to handle.handleStyle?: CSSPropertiesStyle applied to handle.lineClassName?: stringClass name applied to line.lineStyle?: CSSPropertiesStyle applied to line.isVisible?: booleanAre the controls visible.minWidth?: numberMinimum width of node.minHeight?: numberMinimum height of node.maxWidth?: numberMaximum width of node.maxHeight?: numberMaximum height of node.keepAspectRatio?: booleanKeep aspect ratio when resizing.autoScale?: booleanScale the controls with the zoom level.shouldResize?: (event: ResizeDragEvent, params: ResizeParamsWithDirection) => booleanCallback to determine if node should resize.onResizeStart?: OnResizeStartCallback called when resizing starts.onResize?: OnResizeCallback called when resizing.onResizeEnd?: OnResizeEndCallback called when resizing ends.
Examples
Head over to the example page to see how this is done.
Example: examples/nodes/node-resizer
App.jsx
import {
ReactFlow,
Background,
BackgroundVariant,
Controls,
} from '@xyflow/react';
import './index.css';
import ResizableNode from './ResizableNode';
import ResizableNodeSelected from './ResizableNodeSelected';
import CustomResizerNode from './CustomResizerNode';
const nodeTypes = {
ResizableNode,
ResizableNodeSelected,
CustomResizerNode,
};
const initialNodes = [
{
id: '1',
type: 'ResizableNode',
data: { label: 'NodeResizer' },
position: { x: 0, y: 50 },
},
{
id: '2',
type: 'ResizableNodeSelected',
data: { label: 'NodeResizer when selected' },
position: { x: -100, y: 150 },
},
{
id: '3',
type: 'CustomResizerNode',
data: { label: 'Custom Resize Icon' },
position: { x: 150, y: 150 },
style: {
height: 100,
},
},
];
const initialEdges = [];
export default function NodeToolbarExample() {
return (
<ReactFlow
defaultNodes={initialNodes}
defaultEdges={initialEdges}
minZoom={0.2}
maxZoom={4}
fitView
nodeTypes={nodeTypes}
fitViewOptions={{ padding: 0.5 }}
colorMode="system"
>
<Background variant={BackgroundVariant.Dots} />
<Controls />
</ReactFlow>
);
}CustomResizerNode.jsx
import { memo } from 'react';
import { Handle, Position, NodeResizeControl } from '@xyflow/react';
const controlStyle = {
background: 'transparent',
border: 'none',
};
const CustomNode = ({ data }) => {
return (
<>
<NodeResizeControl style={controlStyle} minWidth={100} minHeight={50}>
<ResizeIcon />
</NodeResizeControl>
<Handle type="target" position={Position.Left} />
<div>{data.label}</div>
<Handle type="source" position={Position.Right} />
</>
);
};
function ResizeIcon() {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
width="20"
height="20"
viewBox="0 0 24 24"
strokeWidth="2"
stroke="#ff0071"
fill="none"
strokeLinecap="round"
strokeLinejoin="round"
style={{ position: 'absolute', right: 5, bottom: 5 }}
>
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
<polyline points="16 20 20 20 20 16" />
<line x1="14" y1="14" x2="20" y2="20" />
<polyline points="8 4 4 4 4 8" />
<line x1="4" y1="4" x2="10" y2="10" />
</svg>
);
}
export default memo(CustomNode);ResizableNode.jsx
import { memo } from 'react';
import { Handle, Position, NodeResizer } from '@xyflow/react';
const ResizableNode = ({ data }) => {
return (
<>
<NodeResizer minWidth={100} minHeight={30} />
<Handle type="target" position={Position.Left} />
<div style={{ padding: 10 }}>{data.label}</div>
<Handle type="source" position={Position.Right} />
</>
);
};
export default memo(ResizableNode);ResizableNodeSelected.jsx
import { memo } from 'react';
import { Handle, Position, NodeResizer } from '@xyflow/react';
const ResizableNodeSelected = ({ data, selected }) => {
return (
<>
<NodeResizer
color="#ff0071"
isVisible={selected}
minWidth={100}
minHeight={30}
/>
<Handle type="target" position={Position.Left} />
<div style={{ padding: 10 }}>{data.label}</div>
<Handle type="source" position={Position.Right} />
</>
);
};
export default memo(ResizableNodeSelected);index.css
@import url('@xyflow/react/dist/style.css');
/* we put the theme css at the end to override some of the default css variables and styles */
@import url('./xy-theme.css');
html,
body {
margin: 0;
font-family: sans-serif;
box-sizing: border-box;
}
#app {
width: 100vw;
height: 100vh;
}Custom Resize Controls
To build custom resize controls, you can use the NodeResizeControl component and customize it.
Notes
- Take a look at the docs for the
NodePropstype or the guide on custom nodes to see how to implement your own nodes.