Skip to content

NodePanel

Node container with Root, Header, Content, and Handles slots.

NodePanel is the structural container Workflow Builder uses to render a node on the canvas. It is a compound component: NodePanel.Root orchestrates the layout and accepts up to one of each optional slot — NodePanel.Header, NodePanel.Content, and NodePanel.Handles. Any other child triggers a runtime warning, and each slot may appear at most once.

  • NodePanel.Root - outer wrapper. Takes a selected boolean that drives the selected border / shadow, and arranges the header, handles, and content.
  • NodePanel.Header - the node’s header row, typically holding a NodeIcon and a NodeDescription.
  • NodePanel.Content - the node’s main body. Can be toggled with isVisible.
  • NodePanel.Handles - container for React Flow connection Handles. Supports isVisible and an alignment of 'center' or 'header'.

It composes naturally with the companion building blocks NodeIcon, NodeDescription, and the NodeAsPortWrapper that turns the whole node into a drop target.

NodePanel is composed inside a React Flow node template. The example below mirrors the SDK’s default workflow node: an icon and description in the header, collapsible content in the body, and source / target handles.

import { Collapsible, NodeDescription, NodeIcon, NodePanel, Status } from '@workflowbuilder/ui';
import { Handle, Position } from '@xyflow/react';
function WorkflowNode({ id, icon, label, description, selected, isValid, showHandles = true, children }) {
return (
<Collapsible>
<NodePanel.Root selected={selected}>
<NodePanel.Header>
<NodeIcon icon={icon} />
<NodeDescription label={label} description={description} />
{!!children && <Collapsible.Button />}
</NodePanel.Header>
<NodePanel.Content isVisible={showHandles}>
<Status status={isValid === false ? 'invalid' : undefined} />
<Collapsible.Content>{children}</Collapsible.Content>
</NodePanel.Content>
<NodePanel.Handles isVisible={showHandles} alignment="center">
<Handle id={`${id}-target`} type="target" position={Position.Left} />
<Handle id={`${id}-source`} type="source" position={Position.Right} />
</NodePanel.Handles>
</NodePanel.Root>
</Collapsible>
);
}

selected draws the active outline and shadow. disabled renders the Node Disabled variant: muted surface, title, subtitle and icon, and no hover reaction. The palette uses it for node types that cannot be added at the moment, for example in read-only mode.

PartPropsDescription
NodePanel.Rootselected: boolean, disabled?: boolean, className?, children?Outer wrapper. Lays out header + handles, then content; applies selected and disabled styling.
NodePanel.HeaderclassName?, children?Header row. At most one per Root.
NodePanel.ContentisVisible? (default true), className?, children?Main body. Renders nothing when isVisible is false. At most one per Root.
NodePanel.HandlesisVisible? (default true), alignment? ('center' | 'header', default 'center'), children?Container for connection handles. At most one per Root.

Color

--wb-public-node-port-background-color
--wb-public-node-port-border-color
--wb-public-node-port-background-color-hover
--wb-public-node-port-border-color-hover
--wb-public-node-border-color
--wb-public-node-background-color
--wb-public-node-hover-background-color
--wb-public-node-border-hover-color
--wb-public-node-background-color-disabled
--wb-public-node-border-color-selected

Size

--wb-public-node-port-boundary-size
--wb-public-node-port-size
--wb-public-node-port-size-hover
--wb-public-node-port-border-size
--wb-public-node-width
--wb-public-node-height
--wb-public-node-border-size
--wb-public-node-padding
--wb-public-node-gap
--wb-public-node-border-radius
--wb-public-node-box-shadow-selected