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.
npm install @opendrawjs/react
# or
npm install @opendrawjs/svelteReact
Props: theme, persist, initialElements, ui ('full' | 'none'), onChange, editor, children.
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):
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():
<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><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>