API Reference

Simple Whiteboard API

Everything you can configure, call and listen to. The whiteboard is a single custom element, <simple-whiteboard>, plus a set of tool elements you place in its tools slot.

Installation

Install from npm:

terminal
npm install @ludovicm67/simple-whiteboard

Then import it once anywhere in your JavaScript. The import has the side effect of registering the <simple-whiteboard> custom element and its tools:

main.js
import "@ludovicm67/simple-whiteboard";

Quick start

Drop the element into your markup and add the tool-defaults element to its tools slot to register every built-in tool at once:

index.html
<simple-whiteboard locale="en" dotted-background>
  <simple-whiteboard--tool-defaults slot="tools">
  </simple-whiteboard--tool-defaults>
</simple-whiteboard>

The element sizes itself to its container, so give it a width and a height (for example a full-height <main>).

Attributes

All attributes are optional and can also be set as properties.

AttributeTypeDefaultDescription
localestring"en"The UI language. One of the 24 bundled locales.
dotted-backgroundbooleantrueRender a dotted grid behind the content. Use ="false" to hide it.
hide-locale-pickerbooleanfalseHide the language picker from the menu.
hide-tool-optionsbooleanfalseHide the floating tool-options panel. Handy for a compact or embedded board where it would otherwise cover the canvas.
debugbooleanfalseLog debug information and show the live pointer coordinates.

Tools

Tools are individual custom elements placed in the tools slot. Use tool-defaults for the full set, or cherry-pick only the ones you need to keep the toolbar (and your bundle) lean:

index.html
<simple-whiteboard>
  <simple-whiteboard--tool-pointer slot="tools"></simple-whiteboard--tool-pointer>
  <simple-whiteboard--tool-pen slot="tools"></simple-whiteboard--tool-pen>
  <simple-whiteboard--tool-eraser slot="tools"></simple-whiteboard--tool-eraser>
</simple-whiteboard>

The built-in tool elements:

  • simple-whiteboard--tool-pointer — select, move and resize items
  • simple-whiteboard--tool-move — pan the canvas
  • simple-whiteboard--tool-rect — rectangle
  • simple-whiteboard--tool-circle — circle
  • simple-whiteboard--tool-line — line
  • simple-whiteboard--tool-arrow — arrow
  • simple-whiteboard--tool-pen — freehand pen
  • simple-whiteboard--tool-text — text
  • simple-whiteboard--tool-sticky — sticky note
  • simple-whiteboard--tool-picture — image
  • simple-whiteboard--tool-eraser — object eraser
  • simple-whiteboard--tool-clear — clear the canvas

Methods

Grab the element (document.querySelector("simple-whiteboard")) and call these directly.

History

MethodReturnsDescription
undo()voidUndo the last change.
redo()voidRedo the last undone change.
canUndo()booleanWhether there is anything to undo.
canRedo()booleanWhether there is anything to redo.

Items

MethodReturnsDescription
getItems()Item[]The current items, in stacking order.
getItemById(id)Item | nullLook up a single item.
exportItems()Exported[]Serialize every item to plain JSON.
importItems(items)voidReplace the board with the given exported items.
importItem(item)Item | nullAdd a single exported item.
addItem(item, sendEvent?)voidAppend an item. Emits add unless sendEvent is false.
removeItemById(id, sendEvent?)voidRemove an item by id.
partialItemUpdateById(id, updates, sendEvent?)voidPatch some fields of an item.
clearWhiteboard()voidRemove everything and reset the view.

Stacking order

MethodReturnsDescription
bringItemToFront(id)voidMove an item on top of everything.
sendItemToBack(id)voidMove an item behind everything.
moveItemForward(id)voidMove an item one step towards the front.
moveItemBackward(id)voidMove an item one step towards the back.
applyItemsOrder(orderIds)voidReorder every item to match a list of ids.

View & tools

MethodReturnsDescription
setZoom(zoom)voidSet the zoom level (0.25–4), anchored on the canvas center.
downloadCurrentCanvasAsPng(options?)voidDownload the current view as a PNG. Options: fileName, backgroundColor.
setCurrentTool(name)voidActivate a tool by its name (e.g. "pen").
getCurrentTool()stringThe name of the active tool.
getCanvasElement()HTMLCanvasElement?The underlying canvas, if you need it.

Events

All events are CustomEvents dispatched on the element. Listen with board.addEventListener(name, handler).

EventdetailFired when
ready{ status }The element is initialized and ready.
tool-registered{ name }A tool element has registered itself.
tool-updated{ type, name }The active tool changed.
items-updated{ type, … }The items changed. See the type values below.
history-changed{ canUndo, canRedo }Undo/redo availability changed.

items-updated types

The detail.type tells you what happened, so you can mirror the change to a store or a remote peer:

typeExtra detailMeaning
"add"itemAn item was added.
"update"itemId, itemAn item was fully replaced.
"partial-update"itemId, updatesSome fields of an item changed.
"remove"itemIdAn item was removed.
"reorder"orderThe stacking order changed.
"set"itemsThe whole board changed (e.g. undo/redo).
"clear"The board was cleared.

Theming

Every surface is driven by CSS custom properties. Override them on the element (or any ancestor) to restyle the whole UI:

styles.css
simple-whiteboard {
  --sw-accent: #7c3aed;
  --sw-board: #fbfaff;
  --sw-radius: 14px;
}
PropertyDefaultRole
--sw-board#fcfcffCanvas background.
--sw-surface#ffffffBase panel surface.
--sw-surface-muted#f2f3f5Secondary surface (buttons).
--sw-accent#135aa0Accent for the active tool, focus rings, sliders.
--sw-accent-softrgba(19,90,160,.12)Soft accent fill (active/hover).
--sw-text#1f2933Primary text.
--sw-text-mutedrgba(31,41,51,.55)Secondary text.
--sw-borderrgba(15,23,42,.08)Panel borders.
--sw-radius / --sw-radius-sm10px / 6pxCorner rounding.
--sw-shadowshadowFloating-panel shadow.

Framework usage

Because it’s a standard custom element, it works in any framework. Import once at your entry point, then use the tag in your templates.

React

Use the tag directly (React 19+ handles custom elements natively). Set boolean attributes as you would any DOM attribute, and attach a ref to call methods or listen to events.

Board.jsx
import "@ludovicm67/simple-whiteboard";
import { useEffect, useRef } from "react";

export function Board() {
  const ref = useRef(null);
  useEffect(() => {
    const el = ref.current;
    const onChange = (e) => console.log(e.detail);
    el.addEventListener("items-updated", onChange);
    return () => el.removeEventListener("items-updated", onChange);
  }, []);

  return (
    <simple-whiteboard ref={ref} locale="en">
      <simple-whiteboard--tool-defaults slot="tools" />
    </simple-whiteboard>
  );
}

Collaboration

The whiteboard doesn’t ship a transport — instead, every change emits an items-updated event, and every method takes an optional sendEvent flag so you can apply a remote change without echoing it back. That’s all you need to build real-time sync over any channel (WebSocket, WebRTC, or, as in the demo, a BroadcastChannel between tabs):

collab.js
const channel = new BroadcastChannel("whiteboard");

// Broadcast local changes to peers.
board.addEventListener("items-updated", (e) => {
  if (e.detail.type === "add") {
    channel.postMessage({ type: "add", item: e.detail.item });
  }
});

// Apply remote changes without re-broadcasting (sendEvent = false).
channel.onmessage = (e) => {
  if (e.data.type === "add") board.importItem(e.data.item);
};

See it working: open the live demo in two browser tabs and draw — the boards stay in sync.