Installation & Setup
Three things get you to a working canvas: install the package, import the styles, and give the canvas a size.
1. Install
Pick your edition and install with your package manager of choice. The JointJS tab is the free, open-source package; the JointJS+ tab is the commercial one. It's the same choice you'll see on every example in this guide.
- JointJS
- JointJS+
@joint/react is published on npm:
- npm
- yarn
- bun
npm install @joint/react
yarn add @joint/react
bun add @joint/react
Requirements
- React 18 or 19.
reactandreact-domare peer dependencies, so your project must already have them installed (any React app does). - Any modern React setup.
@joint/reactships both ESM and CommonJS builds, so it drops into Vite, Next.js, Create React App, Remix, and the rest. Starting fresh? Vite (npm create vite@latest) is the quickest.
@joint/core comes with it@joint/react depends on the JointJS engine (@joint/core) and pulls it in automatically. You never import from @joint/core directly to get started; @joint/react re-exports everything you need.
2. Import the stylesheet
The package ships a stylesheet that draws links, ports, highlighters, and the canvas chrome. Import it once, near your app entry point. Without it, links and built-in visuals will not render correctly. Importing it once is enough for the whole app; every example in this guide includes this line.
- JointJS
- JointJS+
import '@joint/react/styles.css';
The diagram chrome it draws is themed through --jj-* CSS variables. Customizing them (and using a CSS framework if you have one) is covered in Theming.
3. Size the canvas
This is the one rule that trips people up: Paper has no width or height props. It fills the element you size with CSS: give its parent, or the Paper itself, a real height, or you will see nothing.
Any CSS works: an inline style, a plain class, CSS Modules, or a utility framework. The examples in this guide use plain CSS, no framework required:
// ✅ Size the Paper directly with an inline style
<Paper renderElement={Element} style={{ height: 500 }} />
// ✅ Or with a plain CSS class
// .canvas { height: 100%; } ← in your stylesheet
<div style={{ height: 500 }}>
<Paper renderElement={Element} className="canvas" />
</div>
// ❌ No size anywhere → 0px tall → blank canvas
<Paper renderElement={Element} />
A percentage height (height: 100%) only works when an ancestor has a concrete height.
You are set up
That is the whole setup: installed, styled, sized. Here is a complete starting point: paste it into your app and you have a draggable two-element diagram:
- JointJS
- JointJS+
import { GraphProvider, Paper, HTMLBox } from '@joint/react'; import '@joint/react/styles.css'; const initialCells = [ { id: '1', type: 'element', position: { x: 300, y: 140 }, data: { label: 'Hello' } }, { id: '2', type: 'element', position: { x: 500, y: 200 }, data: { label: 'World' } }, { id: '1→2', type: 'link', source: { id: '1' }, target: { id: '2' }, style: { targetMarker: 'arrow' }, }, ]; export default function App() { return ( <GraphProvider initialCells={initialCells}> <Paper renderElement={({ label }) => <HTMLBox>{label}</HTMLBox>} style={{ height: 400 }} /> </GraphProvider> ); }
Press Edit above to see and tweak the full App.tsx.
Two elements on a 400px-tall canvas, joined by an arrow. (That third cell with type: 'link' is the connection between them. It lives in the same initialCells array; you'll build links properly in Connecting Elements.) The next chapter breaks this down line by line.
- Blank canvas → the
Paperhas no height. Size it (or its parent) with CSS; see step 3. - Links or visuals look wrong → you forgot
import '@joint/react/styles.css'. - Your HTML doesn't show → wrap it in
HTMLHost. JointJS is SVG-first, so plain HTML needs it. - Elements won't drag → check you didn't set
interactive={false}on thePaper.