Basic usage
The minimum viable DashExcalidraw — one component, default props, a working canvas.
Overview
The smallest useful app is one component with default props. Draw on the canvas below — zoom, pan, undo, the shape tools, the library and the context menu all work with no configuration at all.
That is the point of this page: nothing on it is set up. Everything you can do to the canvas is Excalidraw's own behaviour, reaching Dash unmodified.
What you get for free
Mounting DashExcalidraw with nothing but an id gives you the full editor:
- Every drawing tool — rectangle, diamond, ellipse, arrow, line, freedraw,
text, image, eraser and the frame tool, with keyboard shortcuts (1–9).
- The shape library, including anything the user has saved locally.
- Undo and redo, scoped to this canvas.
- Zoom and pan, including scroll-to-zoom and space-drag.
- The context menu, with copy/paste styles, grouping, layering and locking.
- Excalidraw 0.18's additions — elbow arrows, flowchart shortcuts
(Cmd/Ctrl + arrow key), scene search, image cropping, element linking and the command palette.
None of that costs you a callback.
The minimum app
from dash import Dash
from dash_excalidraw import DashExcalidraw
app = Dash(__name__)
app.layout = DashExcalidraw(id="canvas", height="600px")
if __name__ == "__main__":
app.run(debug=True)
height is the prop you will actually change. Excalidraw fills its parent, so a canvas that looks too short is almost always a container-height problem rather than a component one.
Live demo
Reading what the user drew
The component writes its state back through ordinary props, so a callback reads the canvas the same way it reads a dropdown:
from dash import Input, Output, callback
@callback(Output("count", "children"), Input("canvas", "elements"))
def show(elements):
return f"{len(elements or [])} elements"
elements updates on every scene change. If you only need to know that something changed — not what — read sceneVersion instead; it is a single integer and far cheaper to compare than diffing the element array.
Four switches you may need in a real app
The defaults suit a canvas that owns its page. An app with other inputs, or a canvas embedded in a longer scrolling document, usually wants one or two of these changed.
| Prop | Default | Turn it off when |
|---|---|---|
handleKeyboardGlobally | True | Your page has other inputs. Shortcuts otherwise fire while the user types elsewhere. |
autoFocus | True | The canvas is below the fold, or another field should hold focus on load. |
detectScroll | True | The canvas sits inside a scrolling container and swallowing wheel events feels like a trap. |
langCode | "en" | You want another UI language — "fr-FR", "zh-CN", and so on. |
DashExcalidraw(
id="canvas",
handleKeyboardGlobally=False, # a form on the same page owns the keyboard
autoFocus=False,
detectScroll=False, # the page scrolls; the canvas should not eat it
langCode="fr-FR",
)
handleKeyboardGlobally is the one worth thinking about first. It moves Excalidraw's key handling from the canvas to the document, which is what makes single-key shortcuts work without clicking the canvas — and also what puts it in the same room as every other keyboard consumer on your page. If you have your own shortcuts, a modal, or a form that shares the layout, turn it off and let the canvas take focus before it takes keys.
Where to go next
- initialData — seed the canvas at mount.
- Events — every Excalidraw callback, as a snapshot prop.
- Command dispatch — drive the canvas from Python.
- Persistence — save a scene and restore it later.
Source
# File: docs/basic-usage/basic.py
"""Basic usage: the minimum viable DashExcalidraw."""
import dash_mantine_components as dmc
from dash_excalidraw import DashExcalidraw
from docs._shared import canvas_frame, code_block, sync_canvas_theme
sync_canvas_theme("basic-canvas")
CODE = """
from dash import Dash
from dash_excalidraw import DashExcalidraw
app = Dash(__name__)
app.layout = DashExcalidraw(id='canvas', height='600px')
"""
component = dmc.Stack(
gap="md",
children=[
code_block(CODE),
canvas_frame(DashExcalidraw(id="basic-canvas", height="600px")),
],
)
:defaultExpanded: false :withExpandedButton: true
Component reference
Every prop on the component, generated from the TypeScript source.
Source: /basic
Note for AI agents: This is the static, prerendered view of an interactive Dash application served because we detected a non-JS user agent. Full prose docs:
- /basic/llms.txt — LLM-friendly documentation
- /sitemap.xml
- /robots.txt