Default shapes

The tldraw package includes thirteen shape types that cover common diagramming and whiteboarding needs. Each shape type has a corresponding ShapeUtil that defines its rendering, geometry, and interaction behavior. You can use these shapes as-is, configure their behavior through options, or use them as reference when building custom shapes.

Shape overview

The default shapes loosely fall into five categories based on their primary function:

CategoryShape typesDescription
Texttext, noteText labels and sticky notes
Drawinggeo, draw, line, highlightFreehand strokes, multi-point lines, geometric shapes, and highlights
Mediaimage, video, bookmark, embedExternal content and media files
Structuralframe, groupOrganization and containment
ConnectorsarrowLines that connect shapes together

Basic shapes

Geo

The geo shape renders geometric primitives with optional text labels. It supports 20 different geometric forms—rectangles, ellipses, triangles, stars, polygons, directional arrows, and special shapes like clouds and hearts. Geo shapes can display rich text labels with configurable alignment, making them the foundation for flowcharts, diagrams, and annotated illustrations.

For complete documentation on geometric forms, label positioning, tool interactions, and configuration, see Geo shape.

Quick reference:

PropertyTypeDescription
geoTLGeoShapeGeoStyleThe geometric form
wnumberWidth in pixels
hnumberHeight in pixels
richTextTLRichTextText label displayed inside the shape
colorTLDefaultColorStyleStroke/outline color
labelColorTLDefaultColorStyleText label color (separate from stroke)
fillTLDefaultFillStyleFill style (none, semi, solid, pattern)
dashTLDefaultDashStyleStroke pattern
sizeTLDefaultSizeStyleSize preset affecting stroke width
fontTLDefaultFontStyleFont family for the label
alignTLDefaultHorizontalAlignStyleHorizontal text alignment
verticalAlignTLDefaultVerticalAlignStyleVertical text alignment
growYnumberAdditional vertical space for text overflow
urlstringOptional hyperlink URL
scalenumberScale factor applied to the shape

Text

The text shape displays formatted text content with automatic sizing. Text shapes resize to fit their content by default, or you can set them to a fixed width with text wrapping. The shape supports rich text formatting including bold, italic, and other inline styles.

For a complete guide to text shapes, including auto-size vs fixed-width modes, the text tool's interaction patterns, and configuration options, see Text shape.

editor.createShape({
	type: 'text',
	x: 100,
	y: 100,
	props: {
		richText: toRichText('Hello world'),
		color: 'black',
		size: 'm',
		font: 'draw',
		textAlign: 'start',
		autoSize: true,
		w: 200,
	},
})

Quick reference:

PropertyTypeDescription
richTextTLRichTextThe text content with formatting
colorTLDefaultColorStyleText color
sizeTLDefaultSizeStyleFont size preset (s, m, l, xl)
fontTLDefaultFontStyleFont family (draw, sans, serif, mono)
textAlignTLDefaultTextAlignStyleHorizontal alignment (start, middle, end)
autoSizebooleanWhen true, shape resizes to fit content
wnumberWidth when autoSize is false
scalenumberScale factor applied to the shape

Note

The note shape renders as a sticky note with a colored background and rich text content. Notes have special interaction behaviors: clone handles on the edges let you quickly create adjacent notes, and keyboard shortcuts navigate between them. Notes have a fixed base size but grow vertically to fit their content.

For a complete guide to note interactions, clone handles, keyboard navigation, and configuration, see Note shape.

editor.createShape({
	type: 'note',
	x: 100,
	y: 100,
	props: {
		color: 'yellow',
		labelColor: 'black',
		richText: toRichText('Remember this'),
		size: 'm',
		font: 'draw',
		align: 'middle',
		verticalAlign: 'middle',
	},
})

Drawing shapes

Draw

The draw shape captures freehand strokes and straight line segments. It supports pressure-sensitive input from pens and styluses, automatic shape closing, angle snapping when holding Shift, and hybrid freehand/straight-line drawing modes. Points are stored in a delta-encoded base64 format for efficiency.

For complete documentation on the draw shape and draw tool, including drawing modes, pen support, angle snapping, and programmatic creation, see the Draw shape article.

Quick reference:

PropertyTypeDescription
colorTLDefaultColorStyleStroke color
fillTLDefaultFillStyleFill style (applies when isClosed is true)
dashTLDefaultDashStyleStroke pattern
sizeTLDefaultSizeStyleStroke width preset
segmentsTLDrawShapeSegment[]Array of segments with type and base64-encoded path
isCompletebooleanWhether the user has finished drawing this stroke
isClosedbooleanWhether the path forms a closed shape
isPenbooleanWhether drawn with a stylus (enables pressure-based width)

Line

The line shape creates multi-point lines with draggable handles. Unlike draw shapes, line shapes have explicit control points that you can manipulate after creation. Each point has an ID and index for ordering, allowing points to be added, removed, or repositioned. Lines support both straight segments and smooth cubic spline interpolation.

editor.createShape({
	type: 'line',
	x: 100,
	y: 100,
	props: {
		color: 'black',
		dash: 'solid',
		size: 'm',
		spline: 'line',
		points: {
			a1: { id: 'a1', index: 'a1', x: 0, y: 0 },
			a2: { id: 'a2', index: 'a2', x: 100, y: 50 },
			a3: { id: 'a3', index: 'a3', x: 200, y: 0 },
		},
		scale: 1,
	},
})

Properties:

PropertyTypeDescription
colorTLDefaultColorStyleStroke color
dashTLDefaultDashStyleStroke pattern
sizeTLDefaultSizeStyleStroke width preset
splineTLLineShapeSplineStyleInterpolation: line for straight, cubic for curves
pointsRecord<string, TLLineShapePoint>Dictionary of control points with IDs, indices, and positions
scalenumberScale factor applied to the shape

Line shapes don't have configuration options. The line tool's behavior is controlled through tool configuration rather than the shape utility.

Highlight

The highlight shape works like draw but renders semi-transparently for marking up content. It simulates a highlighter pen, rendering with configurable opacity layers that create the characteristic translucent appearance. Like draw shapes, highlights support pressure-sensitive input and automatic shape splitting for long strokes.

editor.createShape({
	type: 'highlight',
	x: 100,
	y: 100,
	props: {
		color: 'yellow',
		size: 'l',
		segments: [],
		isComplete: true,
		isPen: false,
		scale: 1,
	},
})

Properties:

PropertyTypeDescription
colorTLDefaultColorStyleHighlight color (yellow, green, blue, etc.)
sizeTLDefaultSizeStyleStroke width preset
segmentsTLDrawShapeSegment[]Array of segments with base64-encoded points
isCompletebooleanWhether the user has finished this stroke
isPenbooleanWhether drawn with a stylus
scalenumberScale factor applied to the shape
scaleXnumberHorizontal scale factor for lazy resize
scaleYnumberVertical scale factor for lazy resize

Configuration options:

OptionTypeDefaultDescription
maxPointsPerShapenumber600Maximum points before starting a new shape. Same behavior as draw shapes.
underlayOpacitynumber0.82Opacity of the underlay (background layer). Combined with overlay creates the highlight effect.
overlayOpacitynumber0.35Opacity of the overlay (foreground layer). Lower values create a more subtle highlight.
const ConfiguredHighlightUtil = HighlightShapeUtil.configure({
	maxPointsPerShape: 800,
	underlayOpacity: 0.7,
	overlayOpacity: 0.4,
})

Media shapes

Image

The image shape displays raster images with support for cropping, flipping, and animation control. Images link to asset records that store the actual image data (either as base64 or URLs). The shape maintains aspect ratio during resize and supports circular cropping for profile photos or decorative effects.

editor.createShape({
	type: 'image',
	x: 100,
	y: 100,
	props: {
		w: 400,
		h: 300,
		assetId: 'asset:abc123' as TLAssetId,
		url: '',
		crop: null,
		flipX: false,
		flipY: false,
		playing: true,
		altText: 'Description for accessibility',
	},
})

Properties:

PropertyTypeDescription
wnumberDisplay width in pixels
hnumberDisplay height in pixels
assetIdTLAssetId | nullReference to asset record containing image data
urlstringDirect URL (used when no asset)
cropTLShapeCrop | nullCrop region with topLeft, bottomRight (0-1), and isCircle
flipXbooleanMirror the image horizontally
flipYbooleanMirror the image vertically
playingbooleanWhether animated images (GIFs) should play
altTextstringAccessibility description

Image shapes don't have configuration options. Image handling behavior is controlled through the editor's asset management system.

Video

The video shape displays video content with playback controls. Like images, videos link to asset records. The shape tracks playback position and state, and supports autoplay for automatic playback when the shape becomes visible.

editor.createShape({
	type: 'video',
	x: 100,
	y: 100,
	props: {
		w: 640,
		h: 480,
		assetId: 'asset:video123' as TLAssetId,
		url: '',
		time: 0,
		playing: false,
		autoplay: true,
		altText: 'Video description',
	},
})

Properties:

PropertyTypeDescription
wnumberDisplay width in pixels
hnumberDisplay height in pixels
assetIdTLAssetId | nullReference to asset record
urlstringDirect URL (used when no asset)
timenumberCurrent playback position in seconds
playingbooleanWhether the video is currently playing
autoplaybooleanWhether to start playing automatically
altTextstringAccessibility description

Configuration options:

OptionTypeDefaultDescription
autoplaybooleantrueDefault autoplay behavior for new video shapes.
const ConfiguredVideoUtil = VideoShapeUtil.configure({
	autoplay: false,
})

Bookmark

The bookmark shape displays a URL as a card with metadata including title, description, and preview image. Bookmarks are created when you paste URLs onto the canvas. The editor fetches metadata from the URL and stores it in an associated asset record. Bookmark shapes have fixed dimensions and can't be resized.

editor.createShape({
	type: 'bookmark',
	x: 100,
	y: 100,
	props: {
		url: 'https://example.com',
		assetId: 'asset:bookmark123' as TLAssetId,
		w: 300,
		h: 320,
	},
})

Properties:

PropertyTypeDescription
urlstringThe bookmarked URL
assetIdTLAssetId | nullReference to asset containing title, description, image
wnumberWidth (fixed, not user-resizable)
hnumberHeight (fixed, not user-resizable)

Bookmark shapes don't have configuration options. URL metadata fetching is handled by the editor's external content handlers.

Embed

The embed shape displays interactive content from external services (YouTube, Figma, CodeSandbox, and more) within an iframe. When you paste a URL from a supported service, tldraw automatically converts it to an interactive embed with appropriate dimensions.

For complete documentation on supported services, URL transformation, iframe security, custom embed definitions, and interaction modes, see Embed shape.

editor.createShape({
	type: 'embed',
	x: 100,
	y: 100,
	props: {
		url: 'https://www.youtube.com/watch?v=dQw4w9WgXcQ',
		w: 560,
		h: 315,
	},
})

Properties:

PropertyTypeDescription
urlstringThe original URL (converted to embed URL internally)
wnumberWidth of the embed container
hnumberHeight of the embed container

Structural shapes

Frame

The frame shape provides a visual container for organizing shapes. Shapes inside a frame are clipped to its bounds and move with the frame when it's repositioned. Frames display a header with the frame's name, and optionally colored borders and backgrounds. They're useful for creating sections, organizing content into logical groups, or defining artboard-like regions for export.

editor.createShape({
	type: 'frame',
	x: 100,
	y: 100,
	props: {
		w: 800,
		h: 600,
		name: 'Header Section',
		color: 'blue',
	},
})

Properties:

PropertyTypeDescription
wnumberFrame width in pixels
hnumberFrame height in pixels
namestringLabel displayed in the frame header
colorTLDefaultColorStyleColor for border and header (when colors are enabled)

Configuration options:

OptionTypeDefaultDescription
showColorsbooleanfalseWhen true, frames display colored borders and header backgrounds based on the color property.
resizeChildrenbooleanfalseWhen true, resizing the frame also scales the frame's children proportionally.

When showColors is enabled, the frame's color property becomes a style that users can change from the style panel. When disabled, all frames appear with the same neutral styling.

const ConfiguredFrameUtil = FrameShapeUtil.configure({
	showColors: true,
	resizeChildren: true,
})

Group

The group shape logically combines multiple shapes without visual representation. Groups let you move and transform shapes together while preserving their relative positions. The group's geometry is computed as the union of all child shapes' geometries. Groups are created through the editor API rather than directly, and they delete themselves automatically when their last child is removed or ungrouped.

// Create a group from selected shapes
editor.groupShapes(editor.getSelectedShapeIds())

// Ungroup a group
editor.ungroupShapes([groupId])

// Access group children
const children = editor.getSortedChildIdsForParent(groupId)

Groups have no visual properties; their props object is empty. All visual characteristics come from their child shapes. Their geometry is the union of all child geometries. Groups delete themselves automatically when the last child is removed, and arrows can't bind to them. Double-click a group to enter it and edit children directly.

Group shapes don't have configuration options.

Connectors

Arrow

The arrow shape creates lines that can bind to other shapes. Arrows automatically update when their connected shapes move, maintaining the visual connection. They support two routing modes: arc for smooth curves controlled by a bend parameter, and elbow for right-angle routing that navigates around obstacles. Arrows can display text labels positioned along their length, and offer multiple arrowhead styles for both terminals.

The arrow binding system creates connections automatically when arrow terminals are dragged near other shapes. Bindings can be "precise" (connecting to a specific point) or "imprecise" (connecting to the shape's center or edge).

editor.createShape({
	type: 'arrow',
	x: 100,
	y: 100,
	props: {
		kind: 'arc',
		start: { x: 0, y: 0 },
		end: { x: 200, y: 100 },
		bend: 0,
		color: 'black',
		fill: 'none',
		dash: 'solid',
		size: 'm',
		arrowheadStart: 'none',
		arrowheadEnd: 'arrow',
		font: 'draw',
		richText: toRichText(''),
		labelPosition: 0.5,
		labelColor: 'black',
		scale: 1,
		elbowMidPoint: 0.5,
	},
})

Properties:

PropertyTypeDescription
kindTLArrowShapeKindRouting mode: arc for curved, elbow for right-angle
startVecModelStart terminal position (relative to shape origin)
endVecModelEnd terminal position
bendnumberCurvature for arc arrows (0 = straight)
colorTLDefaultColorStyleStroke color
fillTLDefaultFillStyleFill style (for arrowheads)
dashTLDefaultDashStyleStroke pattern
sizeTLDefaultSizeStyleStroke width preset
arrowheadStartTLArrowShapeArrowheadStyleStart terminal style
arrowheadEndTLArrowShapeArrowheadStyleEnd terminal style
fontTLDefaultFontStyleFont family for label
richTextTLRichTextOptional text label
labelPositionnumberLabel position along arrow (0 = start, 1 = end)
labelColorTLDefaultColorStyleLabel text color
scalenumberScale factor
elbowMidPointnumberPosition of the midpoint handle for elbow arrows

The available arrowhead styles are: none, arrow, triangle, square, dot, pipe, diamond, inverted, bar

Configuration options:

Arrows have extensive configuration options that control snap behavior, timing, and rendering:

OptionTypeDefaultDescription
expandElbowLegLengthRecord<TLDefaultSizeStyle, number>{ s: 28, m: 36, l: 44, xl: 66 }How far elbow arrows extend from target shapes, per size.
minElbowLegLengthRecord<TLDefaultSizeStyle, number>Based on stroke width × 3Minimum length of an elbow arrow's leg segment.
minElbowHandleDistancenumber16Minimum screen pixels between two elbow handles. Closer handles are hidden.
arcArrowCenterSnapDistancenumber16Screen pixels at which arc arrows snap to target shape centers. Set to 0 to disable.
elbowArrowCenterSnapDistancenumber24Screen pixels at which elbow arrows snap to target shape centers.
elbowArrowEdgeSnapDistancenumber20Screen pixels at which elbow arrows snap to target shape edges.
elbowArrowPointSnapDistancenumber24Screen pixels at which elbow arrows snap to directional points (top, right, bottom, left) of shapes.
elbowArrowAxisSnapDistancenumber16Screen pixels at which elbow arrows snap to axes through shape centers.
labelCenterSnapDistancenumber10Screen pixels at which arrow labels snap to the arrow's center when dragged.
elbowMidpointSnapDistancenumber10Screen pixels at which elbow midpoint handles snap to the midpoint between shapes.
elbowMinSegmentLengthToShowMidpointHandlenumber20Minimum segment length before showing the midpoint drag handle.
hoverPreciseTimeoutnumber600Milliseconds to wait while hovering before switching to precise targeting.
pointingPreciseTimeoutnumber320Milliseconds to wait while pointing/dragging before switching to precise targeting.
shouldBeExact(editor: Editor) => booleanReturns editor.inputs.getAltKey()Function determining whether arrows stop exactly at pointer vs. at shape edges.
shouldIgnoreTargets(editor: Editor) => booleanReturns editor.inputs.getCtrlKey()Function determining whether to skip binding to target shapes.
showTextOutlinebooleantrueWhether to show a text outline on arrow labels for readability.
const ConfiguredArrowUtil = ArrowShapeUtil.configure({
	arcArrowCenterSnapDistance: 24,
	hoverPreciseTimeout: 400,
	showTextOutline: false,
	shouldBeExact: (editor) => editor.inputs.getAltKey() || editor.inputs.getShiftKey(),
})

Common properties

All shapes share base properties defined in TLBaseShape:

interface TLBaseShape {
	id: TLShapeId
	type: string
	x: number // Position relative to parent
	y: number
	rotation: number // Rotation in radians
	index: IndexKey // Fractional index for z-ordering
	parentId: TLParentId // Page ID or parent shape ID
	isLocked: boolean
	opacity: number // 0-1
	props: object // Shape-specific properties
	meta: object // Custom metadata (for your application)
}

Most shapes also support common style properties through the style system:

StyleValuesDescription
colorblack, grey, light-violet, etc.Stroke/text color
fillnone, semi, solid, patternFill style
dashsolid, dashed, dotted, drawStroke pattern
sizes, m, l, xlSize preset
fontdraw, sans, serif, monoFont family

Using configured shapes

To use configured shape utilities, pass them to the shapeUtils prop when initializing tldraw. Configured utilities replace the default utilities for their shape type:

import { Tldraw, ArrowShapeUtil, FrameShapeUtil, NoteShapeUtil } from 'tldraw'
import 'tldraw/tldraw.css'

const ConfiguredArrowUtil = ArrowShapeUtil.configure({
	showTextOutline: false,
	hoverPreciseTimeout: 400,
})

const ConfiguredFrameUtil = FrameShapeUtil.configure({
	showColors: true,
})

const ConfiguredNoteUtil = NoteShapeUtil.configure({
	resizeMode: 'scale',
})

export default function App() {
	return (
		<div style={{ position: 'fixed', inset: 0 }}>
			<Tldraw shapeUtils={[ConfiguredArrowUtil, ConfiguredFrameUtil, ConfiguredNoteUtil]} />
		</div>
	)
}

You can also extend shape utilities to add custom behavior beyond configuration options. See the custom shapes guide for details.

  • Custom shape: Create a custom shape utility to understand how default shapes are implemented.
  • Custom styles: Add custom style properties similar to those used by default shapes.
  • Shape options: Configure shape utility behavior using the configure() method.
Prev
Deep links
Next
Drag and drop