Back to Tldraw

Text shape

apps/docs/content/sdk-features/text-shape.mdx

5.4.09.6 KB
Original Source

The text shape displays formatted text on the canvas. It has two modes: auto-size, where the shape grows to fit its content, and fixed-width, where text wraps at a set width. The text tool creates text shapes. See TextShapeUtil and TLTextShape.

Auto-size vs fixed-width

Text shapes operate in two modes controlled by the autoSize property:

ModeBehaviorUse case
Auto-sizeShape width expands to fit content; text never wrapsLabels, titles, short annotations
Fixed-widthText wraps at the shape's width boundary; height grows as neededParagraphs, longer descriptions, callouts

Auto-size mode

When autoSize is true (the default), the shape grows to fit its text. The shape widens as you type, and text never wraps unless you press Enter.

tsx
import { toRichText } from 'tldraw'

editor.createShape({
	type: 'text',
	x: 100,
	y: 100,
	props: {
		richText: toRichText('This text will never wrap'),
		autoSize: true,
	},
})

Which edge stays put as an auto-sized shape grows depends on textAlign: with start the left edge stays fixed and the shape grows to the right, with middle the center stays fixed, and with end the right edge stays fixed.

Fixed-width mode

When autoSize is false, the shape uses a fixed width specified by the w property. Text wraps when it reaches this boundary, and the shape grows vertically to accommodate additional lines.

tsx
editor.createShape({
	type: 'text',
	x: 100,
	y: 100,
	props: {
		richText: toRichText('This text will wrap when it reaches the specified width'),
		autoSize: false,
		w: 200, // Width in pixels
	},
})

To convert an auto-sized shape to fixed-width, drag its left or right edge handle. The shape switches to fixed-width mode and keeps that width as you type.

Text alignment

The textAlign property controls horizontal text alignment:

ValueDescription
startLeft-aligned (or right-aligned in RTL locales)
middleCenter-aligned
endRight-aligned (or left-aligned in RTL locales)
tsx
editor.createShape({
	type: 'text',
	x: 100,
	y: 100,
	props: {
		richText: toRichText('Centered text'),
		textAlign: 'middle',
		autoSize: false,
		w: 300,
	},
})

Text shapes always align vertically to the middle of the shape's geometry.

Creating text with the text tool

The text tool (T key) creates text shapes in two ways. Double-clicking empty canvas with the select tool also creates an auto-sized text shape.

Click to create auto-sized text

Click anywhere on the canvas to create an auto-sized text shape. The shape appears centered at your click position and immediately enters edit mode. Start typing to add content.

Drag to create fixed-width text

Hold and drag horizontally to create a fixed-width text shape. Once the pointer has been down for at least 150ms and the horizontal drag exceeds about six times the base drag distance (larger for coarse pointers, scaled by zoom), the tool creates a fixed-width shape at that width and hands off to the select tool's resize state. Keep dragging to adjust the width, then release to start editing. Quick, short drags create auto-sized shapes instead.

Tool shortcuts

ActionResult
ClickCreate auto-sized text at click position
Drag horizontallyCreate fixed-width text with dragged width
Enter (shape selected)Switch to the select tool and edit the shape
EscapeExit text tool, return to select tool
Cmd/Ctrl+EnterConfirm text and exit edit mode

Editing text

Double-click a text shape or press Enter while it's selected to enter edit mode. The shape displays a cursor and you can type, select, and format text using the rich text editor.

Text shapes use the same rich text system as notes, geo shapes, and arrow labels. You get bold, italic, code, highlighting, and more through keyboard shortcuts or the rich text toolbar.

Empty text deletion

When editing ends, the shape deletes itself if its text is empty or only trailing whitespace. This keeps invisible shapes off the canvas.

Scaling and resize

Text shapes support two resize behaviors:

Aspect-ratio locked scaling

Dragging any handle other than the left or right edges scales the whole shape proportionally. The scale property tracks this multiplier.

tsx
// A text shape at 2x scale
editor.createShape({
	type: 'text',
	props: {
		richText: toRichText('Scaled up'),
		scale: 2,
	},
})

Width adjustment

Dragging the left or right edge handles adjusts only the width. For auto-sized shapes, this converts them to fixed-width mode. For already fixed-width shapes, this changes where text wraps.

Dynamic resize mode

When editor.user.getIsDynamicResizeMode() is true, new text shapes are created with a scale inversely proportional to the current zoom level. At 200% zoom, new shapes get scale: 0.5; at 50% zoom, they get scale: 2. This keeps text visually consistent regardless of your zoom level when creating it. Use Editor#getResizeScaleFactor to get the same value:

tsx
const scale = editor.getResizeScaleFactor()

Arrow bindings

Arrows can bind to text shapes just like other shapes. When an arrow with no arrowhead binds to a text shape, the shape's geometry is widened by extraArrowHorizontalPadding on each side (10 by default) so the bare line ends short of the glyphs. Arrows with arrowheads bind to the unpadded box. See Configuration to change the padding.

Text outline

Text shapes display an outline in the canvas background color, which keeps text readable when it overlaps other shapes. The outline uses CSS text-shadow and is on by default. Safari skips it because text-shadow performs poorly there. Turn it off with the showTextOutline option (see Configuration).

Properties

PropertyTypeDefaultDescription
richTextTLRichTextemptyText content with formatting
colorTLDefaultColorStyle'black'Text color
sizeTLDefaultSizeStyle'm'Font size preset (s, m, l, xl)
fontTLDefaultFontStyle'draw'Font family (draw, sans, serif, mono)
textAlignTLDefaultTextAlignStyle'start'Horizontal alignment (start, middle, end)
autoSizebooleantrueWhen true, shape resizes to fit content
wnumber8Width when autoSize is false
scalenumber1Scale factor applied to the shape

Configuration

OptionTypeDefaultDescription
extraArrowHorizontalPaddingnumber10Extra horizontal padding when an arrow without an arrowhead binds
showTextOutlinebooleantrueDisplay text outline for readability (skipped on Safari for performance)
tsx
import { Tldraw, TextShapeUtil } from 'tldraw'
import 'tldraw/tldraw.css'

const ConfiguredTextUtil = TextShapeUtil.configure({
	extraArrowHorizontalPadding: 20,
	showTextOutline: false,
})

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

Grid snapping

When grid mode is enabled (editor.getInstanceState().isGridMode), the text tool snaps new text shapes to the grid.

Programmatic text formatting

To create text with formatting, construct the rich text JSON structure directly:

tsx
editor.createShape({
	type: 'text',
	x: 100,
	y: 100,
	props: {
		richText: {
			type: 'doc',
			content: [
				{
					type: 'paragraph',
					content: [
						{ type: 'text', text: 'Regular and ' },
						{ type: 'text', text: 'bold', marks: [{ type: 'bold' }] },
						{ type: 'text', text: ' text' },
					],
				},
			],
		},
		autoSize: true,
	},
})

Marks include bold, italic, strike, underline, code, link, and highlight. See Rich text for the formatting system.

  • Rich text — Text formatting system and TipTap integration
  • Default shapes — Overview of all built-in shapes
  • Tools — How tools handle user input
  • Styles — Working with shape styles like color and size