React and Svelte

Use the opendraw whiteboard in React 18+ and Svelte 5: the OpenDraw component, styles, driving the editor from outside and reactive state.

React & Svelte

The editor also ships as React and Svelte 5 components, over the same @opendrawjs/editor. Each offers a ready-made <OpenDraw>, canvas, toolbar with key hints, zoom and history islands, theme toggle and autosave, and a bare <OpenDrawCanvas> for your own UI. One Playwright suite runs against both, so they behave identically.

terminal
npm install @opendrawjs/react
# or
npm install @opendrawjs/svelte

React

Props: theme, persist, initialElements, ui ('full' | 'none'), onChange, editor, children.

Board.tsx
import '@opendrawjs/editor/styles.css'
import { OpenDraw } from '@opendrawjs/react'

export function Board() {
  return (
    <div style={{ height: '100vh' }}>
      <OpenDraw theme="system" onChange={(state) => save(state.elements)} />
    </div>
  )
}

useOpenDrawEditor() creates a controller for the component's lifetime and useEditorState(editor, read) subscribes to any slice of it (built on useSyncExternalStore):

MyBoard.tsx
import { OpenDrawCanvas, useEditorState, useOpenDrawEditor } from '@opendrawjs/react'

export function MyBoard() {
  const editor = useOpenDrawEditor()
  const tool = useEditorState(editor, (e) => e.activeTool)

  return (
    <div className="opendraw" data-opendraw-root>
      <OpenDrawCanvas editor={editor} />
      <button aria-pressed={tool === 'rectangle'} onClick={() => editor.setActiveTool('rectangle')}>
        Rectangle
      </button>
    </div>
  )
}

Svelte

The same props, with Svelte's onchange naming. State is read through runes-friendly editorState():

Board.svelte
<script lang="ts">
  import '@opendrawjs/editor/styles.css'
  import { OpenDraw } from '@opendrawjs/svelte'
</script>

<div style="height: 100vh">
  <OpenDraw theme="system" onchange={(state) => save(state.elements)} />
</div>
MyBoard.svelte
<script lang="ts">
  import { OpenDrawCanvas, createEditor, editorState } from '@opendrawjs/svelte'

  const editor = createEditor()
  const tool = editorState(editor, (e) => e.activeTool)
</script>

<div class="opendraw" data-opendraw-root>
  <OpenDrawCanvas {editor} />
  <button aria-pressed={tool.current === 'rectangle'} onclick={() => editor.setActiveTool('rectangle')}>
    Rectangle
  </button>
</div>