Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/tldraw/tldraw/llms.txt

Use this file to discover all available pages before exploring further.

The Tldraw and TldrawEditor components are the primary React components for integrating tldraw into your application.

Tldraw

The complete “batteries included” tldraw component with UI, shapes, and tools.
import { Tldraw } from 'tldraw'
import 'tldraw/tldraw.css'

function App() {
  return (
    <div style={{ position: 'fixed', inset: 0 }}>
      <Tldraw />
    </div>
  )
}

Props

store
TLStore | TLStoreWithStatus
A store to use for the editor’s data. If not provided, a new store will be created.
const store = createTLStore({ shapeUtils: [...] })
<Tldraw store={store} />
shapeUtils
TLAnyShapeUtilConstructor[]
Array of custom shape utility classes. These will be merged with the default shapes.
<Tldraw shapeUtils={[MyCustomShapeUtil]} />
bindingUtils
TLAnyBindingUtilConstructor[]
Array of custom binding utility classes for managing shape relationships.
tools
TLStateNodeConstructor[]
Array of custom tool classes. These will be merged with the default tools.
<Tldraw tools={[MyCustomTool]} />
components
TLComponents
Custom React components to override default UI elements.
<Tldraw 
  components={{
    Toolbar: MyCustomToolbar,
    KeyboardShortcutsDialog: null, // Disable keyboard shortcuts dialog
    Scribble: MyCustomScribble
  }} 
/>
onMount
(editor: Editor) => void
Callback that fires when the editor is mounted and ready.
<Tldraw 
  onMount={(editor) => {
    console.log('Editor ready!', editor)
    editor.createShape({ type: 'geo', x: 100, y: 100 })
  }} 
/>
initialState
string
The initial active tool or state. Defaults to ‘select’.
<Tldraw initialState="draw" />
autoFocus
boolean
Whether to automatically focus the editor when it mounts. Defaults to true.
inferDarkMode
boolean
Whether to infer dark mode from the user’s system preferences. Defaults to false.
hideUi
boolean
Hide all UI elements. Useful when you want to build a completely custom UI.
<Tldraw hideUi />
assetUrls
TLUiAssetUrlOverrides
Custom URLs for assets like icons and fonts.
const assetUrls = {
  icons: '/custom-icons/',
  fonts: '/custom-fonts/'
}
<Tldraw assetUrls={assetUrls} />
embeds
TLEmbedDefinition[]
Custom embed definitions for embedding external content.
const customEmbeds = [
  {
    type: 'myembed',
    title: 'My Custom Embed',
    hostnames: ['mysite.com'],
    // ... more configuration
  }
]
<Tldraw embeds={customEmbeds} />
acceptedImageMimeTypes
string[]
MIME types to accept for image uploads. Defaults to common image formats.
acceptedVideoMimeTypes
string[]
MIME types to accept for video uploads. Defaults to common video formats.
maxImageDimension
number
Maximum dimension (width or height) for uploaded images. Images larger than this will be resized.
maxAssetSize
number
Maximum file size in bytes for uploaded assets.

Complete example

import { Tldraw } from 'tldraw'
import 'tldraw/tldraw.css'

function MyApp() {
  return (
    <div style={{ position: 'fixed', inset: 0 }}>
      <Tldraw
        onMount={(editor) => {
          // Add initial shapes
          editor.createShapes([
            {
              type: 'geo',
              x: 100,
              y: 100,
              props: { w: 100, h: 100, geo: 'rectangle' }
            }
          ])
        }}
        components={{
          Toolbar: () => <div>My Custom Toolbar</div>
        }}
        hideUi={false}
        inferDarkMode={true}
      />
    </div>
  )
}

TldrawEditor

The core editor component without UI. Use this when you want complete control over the interface.
import { TldrawEditor } from '@tldraw/editor'
import '@tldraw/editor/editor.css'

function App() {
  return (
    <TldrawEditor
      shapeUtils={defaultShapeUtils}
      bindingUtils={defaultBindingUtils}
      tools={defaultTools}
    >
      <YourCustomUI />
    </TldrawEditor>
  )
}

Props

store
TLStore | TLStoreWithStatus
required
A store instance for the editor’s data. Can be created with createTLStore.
const store = createTLStore({ 
  shapeUtils: defaultShapeUtils,
  bindingUtils: defaultBindingUtils 
})

<TldrawEditor store={store} />
shapeUtils
TLAnyShapeUtilConstructor[]
required
Array of shape utility classes. Unlike Tldraw, you must provide these explicitly.
import { defaultShapeUtils } from 'tldraw'

<TldrawEditor shapeUtils={defaultShapeUtils} />
bindingUtils
TLAnyBindingUtilConstructor[]
required
Array of binding utility classes.
import { defaultBindingUtils } from 'tldraw'

<TldrawEditor bindingUtils={defaultBindingUtils} />
tools
TLStateNodeConstructor[]
required
Array of tool classes.
import { defaultTools } from 'tldraw'

<TldrawEditor tools={defaultTools} />
components
TLEditorComponents
Custom React components for editor elements (not UI elements).
<TldrawEditor 
  components={{
    Scribble: MyCustomScribble,
    ShapeIndicators: MyCustomIndicators,
    Handles: MyCustomHandles
  }} 
/>
onMount
(editor: Editor) => void
Callback when the editor is ready.
initialState
string
The initial active tool or state.
autoFocus
boolean
Whether to automatically focus the editor.
options
Partial<TldrawOptions>
Editor configuration options including camera and text settings.

Example with custom UI

import { TldrawEditor, useEditor } from '@tldraw/editor'
import { defaultShapeUtils, defaultBindingUtils, defaultTools } from 'tldraw'
import '@tldraw/editor/editor.css'

function CustomToolbar() {
  const editor = useEditor()
  
  return (
    <div style={{ position: 'absolute', top: 0, left: 0 }}>
      <button onClick={() => editor.setCurrentTool('select')}>Select</button>
      <button onClick={() => editor.setCurrentTool('draw')}>Draw</button>
      <button onClick={() => editor.undo()}>Undo</button>
      <button onClick={() => editor.redo()}>Redo</button>
    </div>
  )
}

function App() {
  return (
    <div style={{ position: 'fixed', inset: 0 }}>
      <TldrawEditor
        shapeUtils={defaultShapeUtils}
        bindingUtils={defaultBindingUtils}
        tools={defaultTools}
      >
        <CustomToolbar />
      </TldrawEditor>
    </div>
  )
}

Accessing the editor instance

Use the useEditor hook to access the editor instance within child components:
import { useEditor } from '@tldraw/editor'

function MyComponent() {
  const editor = useEditor()
  
  const handleClick = () => {
    const selectedShapes = editor.getSelectedShapes()
    console.log('Selected:', selectedShapes)
  }
  
  return <button onClick={handleClick}>Log Selection</button>
}

Store creation

Create a store to persist data or control initialization:
import { createTLStore, defaultShapeUtils, defaultBindingUtils } from 'tldraw'

const store = createTLStore({
  shapeUtils: defaultShapeUtils,
  bindingUtils: defaultBindingUtils
})

// Load data from storage
const snapshot = localStorage.getItem('my-drawing')
if (snapshot) {
  store.loadSnapshot(JSON.parse(snapshot))
}

// Save data to storage
store.listen((changes) => {
  const snapshot = store.getSnapshot()
  localStorage.setItem('my-drawing', JSON.stringify(snapshot))
})

function App() {
  return <Tldraw store={store} />
}