Web component
Drop a canvas into any framework, or none, with the canvas-flow custom element.
<canvas-flow> is a custom element that wraps the web host. Every framework can render it, and plain HTML can too. It is the right choice when your framework has no binding, or when the canvas is a small part of a page.
A board in HTML#
<canvas-flow id="board" persistence-key="board" style="height: 100vh"></canvas-flow>
<script type="module">
import { defineCanvasFlowElement } from 'canvasflow/dom'
import { mountUI } from 'canvasflow/ui'
defineCanvasFlowElement()
// Extensions run with the app. Mount the default UI, or add your own.
document.getElementById('board').extensions = [
(app) => {
const ui = mountUI(app)
return () => ui.destroy()
},
]
</script>
Without an extension the element is a bare canvas with all the editing behavior and no toolbar. That is on purpose: the element lives in canvasflow/dom, which never imports the default UI.
Attributes and properties#
| Attribute | What it does |
|---|---|
persistence-key |
Autosave under this key. Read when the element connects. |
theme |
light or dark. |
readonly |
View only. |
grid |
dots, lines or none. |
dir |
The element's own dir decides the layout direction (and so does any ancestor's). See Right to left. |
| Property | What it is |
|---|---|
.editor, .app |
The editor and the app, once connected. |
.options |
Options for createCanvasFlow. Set before the element connects. |
.extensions |
Functions that receive the app and may return a cleanup. Set before or after the element connects. |
The element dispatches a bubbling canvasflow-ready event with detail: { app, editor } when it is ready.
document.addEventListener('canvasflow-ready', (event) => {
const { editor } = (event as CustomEvent).detail
editor.zoomToFit()
})
In a framework#
The element works anywhere HTML does. In Angular add CUSTOM_ELEMENTS_SCHEMA; in Vue tell the compiler it is a custom element (isCustomElement: (tag) => tag === 'canvas-flow'); React 19 and Preact pass properties to custom elements natively. If the framework has a binding here, prefer it: you get the editor as reactive state.