Custom Elements & Styling
Here is where @joint/react pays off: an element is just a React component. No element-type registry, no base class. If you can build a card in React, you can put it on the canvas.
Here are the same workflow steps, now with real shape: an icon, label, and description, plus ports, the small connection points the next chapter wires together.
- JointJS
- JointJS+
import { GraphProvider, Paper, HTMLHost, type ElementPort, } from '@joint/react'; import '@joint/react/styles.css'; import './example.css'; type NodeData = { label: string; description: string; icon: string; color: string; }; // Two ports: an input on the left, an output on the right. const ports: Record<string, ElementPort> = { in: { cx: 0, cy: '50%', width: 10, height: 10, passive: true }, out: { cx: '100%', cy: '50%', width: 10, height: 10 }, }; const initialCells = [ { id: 'trigger', type: 'element', position: { x: 60, y: 60 }, size: { width: 160, height: 52 }, portMap: ports, data: { label: 'New Ticket', description: 'Listens for events', icon: '⚡', color: '#f59e0b' }, }, { id: 'agent', type: 'element', position: { x: 60, y: 170 }, size: { width: 160, height: 52 }, portMap: ports, data: { label: 'Classify', description: 'Runs an AI model', icon: '