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 UI system is highly customizable. You can override components, modify actions and tools, change translations, and adjust the appearance to match your application’s design.
Component overrides
Replace any UI component with your own implementation:
import { Tldraw , TLUiComponents } from 'tldraw'
import 'tldraw/tldraw.css'
function CustomToolbar () {
return (
< div className = "my-custom-toolbar" >
{ /* Your custom toolbar */ }
</ div >
)
}
const components : Partial < TLUiComponents > = {
Toolbar: CustomToolbar ,
}
export default function App () {
return < Tldraw components = { components } />
}
Removing components
Set a component to null to remove it entirely:
const components : Partial < TLUiComponents > = {
HelpMenu: null ,
SharePanel: null ,
TopPanel: null ,
}
export default function App () {
return < Tldraw components = { components } />
}
Extending existing components
Wrap or extend default components:
import {
Tldraw ,
DefaultToolbar ,
TldrawUiButton ,
TldrawUiButtonIcon ,
useEditor ,
} from 'tldraw'
import 'tldraw/tldraw.css'
function CustomToolbar () {
const editor = useEditor ()
return (
< div className = "custom-toolbar-wrapper" >
< DefaultToolbar />
< div className = "extra-tools" >
< TldrawUiButton
type = "tool"
onClick = { () => {
// Custom action
console . log ( 'Custom tool clicked' )
} }
>
< TldrawUiButtonIcon icon = "plus" />
</ TldrawUiButton >
</ div >
</ div >
)
}
export default function App () {
return < Tldraw components = { { Toolbar: CustomToolbar } } />
}
Action overrides
Modify or add custom actions to the editor:
import { Tldraw , TLUiOverrides } from 'tldraw'
import 'tldraw/tldraw.css'
const overrides : TLUiOverrides = {
actions ( editor , actions , helpers ) {
return {
... actions ,
'my-custom-action' : {
id: 'my-custom-action' ,
label: 'My custom action' ,
kbd: '$u' ,
icon: 'heart' ,
onSelect () {
// Custom action logic
const selectedShapes = editor . getSelectedShapes ()
console . log ( 'Custom action:' , selectedShapes )
},
},
// Override existing action
copy: {
... actions . copy ,
onSelect () {
// Custom copy logic
console . log ( 'Custom copy' )
actions . copy . onSelect ( 'menu' )
},
},
}
},
}
export default function App () {
return < Tldraw overrides = { overrides } />
}
Using helper functions
The helpers parameter provides useful utilities:
const overrides : TLUiOverrides = {
actions ( editor , actions , helpers ) {
return {
... actions ,
'export-with-toast' : {
id: 'export-with-toast' ,
label: 'Export with notification' ,
onSelect () {
helpers . exportAs ( editor . getSelectedShapes (), 'png' )
helpers . addToast ({
title: 'Exported!' ,
description: 'Your shapes have been exported.' ,
})
},
},
}
},
}
Available helpers:
addToast() - Show toast notification
removeToast() - Remove toast
clearToasts() - Clear all toasts
addDialog() - Show dialog
removeDialog() - Remove dialog
clearDialogs() - Clear all dialogs
msg() - Get translated message
isMobile - Check if mobile
insertMedia() - Insert media files
exportAs() - Export content
copyAs() - Copy content
printSelectionOrPages() - Print content
Add custom tools or modify existing ones:
import { Tldraw , TLUiOverrides } from 'tldraw'
import 'tldraw/tldraw.css'
const overrides : TLUiOverrides = {
tools ( editor , tools , helpers ) {
return {
... tools ,
'my-custom-tool' : {
id: 'my-custom-tool' ,
label: 'Custom tool' ,
icon: 'color' ,
kbd: '$c' ,
onSelect () {
editor . setCurrentTool ( 'my-custom-tool' )
},
},
}
},
}
export default function App () {
return < Tldraw overrides = { overrides } />
}
Tool overrides only add UI elements. To implement the actual tool behavior, you need to create a custom StateNode and add it to the editor’s tools. See the Custom tools guide.
Translation overrides
Customize or add translations:
import { Tldraw , TLUiOverrides } from 'tldraw'
import 'tldraw/tldraw.css'
const overrides : TLUiOverrides = {
translations: {
en: {
'action.copy' : 'Copy to clipboard' ,
'action.paste' : 'Paste from clipboard' ,
'my-custom-action' : 'My Custom Action' ,
},
es: {
'my-custom-action' : 'Mi Acción Personalizada' ,
},
},
}
export default function App () {
return < Tldraw overrides = { overrides } />
}
See the Translations page for more details.
Multiple overrides
Combine multiple override objects:
import { Tldraw , TLUiOverrides } from 'tldraw'
import 'tldraw/tldraw.css'
const actionOverrides : TLUiOverrides = {
actions ( editor , actions ) {
return {
... actions ,
'custom-action' : {
id: 'custom-action' ,
label: 'Custom' ,
onSelect () { /* ... */ },
},
}
},
}
const toolOverrides : TLUiOverrides = {
tools ( editor , tools ) {
return {
... tools ,
'custom-tool' : {
id: 'custom-tool' ,
label: 'Custom Tool' ,
onSelect () { /* ... */ },
},
}
},
}
export default function App () {
return < Tldraw overrides = { [ actionOverrides , toolOverrides ] } />
}
Customize what appears in menus by providing custom children to menu components:
import {
Tldraw ,
DefaultMainMenu ,
TldrawUiMenuGroup ,
TldrawUiMenuItem ,
useEditor ,
} from 'tldraw'
import 'tldraw/tldraw.css'
function CustomMainMenu () {
const editor = useEditor ()
return (
< DefaultMainMenu >
< TldrawUiMenuGroup id = "custom" >
< TldrawUiMenuItem
id = "custom-item"
label = "Custom Item"
icon = "heart"
onSelect = { () => {
console . log ( 'Custom item selected' )
} }
/>
</ TldrawUiMenuGroup >
</ DefaultMainMenu >
)
}
export default function App () {
return < Tldraw components = { { MainMenu: CustomMainMenu } } />
}
Customizing toolbar content
Modify what tools appear in the toolbar:
import {
Tldraw ,
DefaultToolbar ,
SelectToolbarItem ,
HandToolbarItem ,
DrawToolbarItem ,
EraserToolbarItem ,
TextToolbarItem ,
RectangleToolbarItem ,
EllipseToolbarItem ,
} from 'tldraw'
import 'tldraw/tldraw.css'
function CustomToolbar () {
return (
< DefaultToolbar >
< SelectToolbarItem />
< HandToolbarItem />
< DrawToolbarItem />
< EraserToolbarItem />
< TextToolbarItem />
< RectangleToolbarItem />
< EllipseToolbarItem />
{ /* Only these tools will appear */ }
</ DefaultToolbar >
)
}
export default function App () {
return < Tldraw components = { { Toolbar: CustomToolbar } } />
}
Custom styling with CSS
Override tldraw’s CSS variables to customize colors and appearance:
/* Custom theme colors */
.tl-theme__light {
--color-primary : #ff0000 ;
--color-text : #333333 ;
--color-background : #ffffff ;
--color-panel : #f5f5f5 ;
}
.tl-theme__dark {
--color-primary : #ff6b6b ;
--color-text : #ffffff ;
--color-background : #1a1a1a ;
--color-panel : #2d2d2d ;
}
/* Customize toolbar */
.tlui-main-toolbar {
background : var ( --color-panel );
border-radius : 12 px ;
padding : 8 px ;
}
/* Customize buttons */
.tlui-button {
border-radius : 8 px ;
}
.tlui-button__tool [ data-isactive = 'true' ] {
background : var ( --color-primary );
}
Then import your custom CSS after tldraw’s CSS:
import 'tldraw/tldraw.css'
import './custom-theme.css'
export default function App () {
return < Tldraw />
}
Asset URL overrides
Customize where icons, fonts, and translations are loaded from:
import { Tldraw } from 'tldraw'
import 'tldraw/tldraw.css'
export default function App () {
return (
< Tldraw
assetUrls = { {
icons: {
'tool-pointer' : '/custom-icons/pointer.svg' ,
// ... other icons
},
fonts: {
draw: '/custom-fonts/draw.woff2' ,
sans: '/custom-fonts/sans.woff2' ,
serif: '/custom-fonts/serif.woff2' ,
mono: '/custom-fonts/mono.woff2' ,
},
translations: {
en: '/custom-translations/en.json' ,
// ... other languages
},
} }
/>
)
}
Theming with class names
Add custom class names to control theming:
import { Tldraw } from 'tldraw'
import 'tldraw/tldraw.css'
export default function App () {
return (
< div className = "my-custom-theme" >
< Tldraw />
</ div >
)
}
.my-custom-theme .tlui-layout {
/* Custom styles scoped to your theme */
}
Custom top panel
Add custom content to the top center of the UI:
import { Tldraw } from 'tldraw'
import 'tldraw/tldraw.css'
function CustomTopPanel () {
return (
< div style = { { padding: '8px' } } >
< h1 > My Custom App </ h1 >
</ div >
)
}
export default function App () {
return < Tldraw components = { { TopPanel: CustomTopPanel } } />
}
Readonly mode customization
Customize behavior in readonly mode:
import { Tldraw , useEditor } from 'tldraw'
import 'tldraw/tldraw.css'
function CustomToolbar () {
const editor = useEditor ()
const isReadonly = editor . getInstanceState (). isReadonly
if ( isReadonly ) {
return < div > View-only mode </ div >
}
return < DefaultToolbar />
}
export default function App () {
return (
< Tldraw
components = { { Toolbar: CustomToolbar } }
onMount = { ( editor ) => {
editor . updateInstanceState ({ isReadonly: true })
} }
/>
)
}
Next steps
Menus and toolbars Deep dive into customizing menus and toolbars
Translations Add custom translations and support multiple languages
Custom tools Create custom tools with full behavior