Back to Tldraw

Geo shape

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

5.4.013.8 KB
Original Source

The geo shape is one of the default shapes in tldraw. It renders one of 20 built-in geometric forms (rectangles, ellipses, stars, clouds, and more) with an optional rich text label. Geo shapes are the usual building blocks for flowcharts and diagrams.

Geometric forms

The geo shape supports a variety of built-in forms, grouped by type:

Basic shapes

FormDescription
rectangleFour-sided shape with right angles (default)
ellipseOval or circular shape
triangleThree-sided shape pointing upward
diamondSquare rotated 45 degrees
ovalStadium shape (rectangle with rounded ends)

Polygons

FormDescription
pentagonFive-sided regular polygon
hexagonSix-sided regular polygon
octagonEight-sided regular polygon
starFive-pointed star

Parallelograms

FormDescription
rhombusParallelogram slanted to the right
rhombus-2Parallelogram slanted to the left
trapezoidFour-sided shape with parallel top and bottom

Directional arrows

FormDescription
arrow-upBlock arrow pointing upward
arrow-downBlock arrow pointing downward
arrow-leftBlock arrow pointing left
arrow-rightBlock arrow pointing right

Special shapes

FormDescription
cloudOrganic cloud shape with randomly varied bumps
heartHeart shape
x-boxRectangle with an X through it
check-boxRectangle with a checkmark inside

Creating geo shapes

Create a geo shape using Editor#createShape:

tsx
import { toRichText } from 'tldraw'

editor.createShape({
	type: 'geo',
	x: 100,
	y: 100,
	props: {
		geo: 'rectangle',
		w: 200,
		h: 150,
		color: 'blue',
		fill: 'solid',
		dash: 'draw',
		size: 'm',
	},
})

Adding text labels

Geo shapes support rich text labels positioned inside the shape:

tsx
editor.createShape({
	type: 'geo',
	x: 100,
	y: 100,
	props: {
		geo: 'ellipse',
		w: 200,
		h: 150,
		richText: toRichText('Process step'),
		labelColor: 'black',
		align: 'middle',
		verticalAlign: 'middle',
		font: 'draw',
	},
})

The label text wraps within the shape bounds. When text overflows the shape height, the shape grows vertically and tracks the extra height in growY. If the label's minimum width is wider than the shape, the shape widens to fit it.

Changing the geometric form

Switch between forms by updating the geo property:

tsx
// Change a rectangle to an ellipse
editor.updateShape({
	id: shapeId,
	type: 'geo',
	props: {
		geo: 'ellipse',
	},
})

You can also set the default geometric form for the geo tool by updating the style for the next shape:

tsx
import { GeoShapeGeoStyle } from 'tldraw'

// Set the default geo style to star
editor.setStyleForNextShapes(GeoShapeGeoStyle, 'star')

The geo tool's toolbar shortcuts are R for rectangle and O for ellipse.

Using the geo tool

The geo tool creates shapes through click or click-and-drag interactions.

Click to create

Click anywhere on the canvas to create a shape at the default size. The shape centers on your click position. Different geometric forms have different default sizes:

FormDefault size
star200 × 190
cloud300 × 180
Other200 × 200

Click and drag to create

Click and drag to create a shape at a custom size. The shape's corner follows your pointer as you drag. Release to complete the shape.

Editing labels

Press Enter while a geo shape is selected to edit its label. The shape enters edit mode, where you can type or modify the rich text content. Press Escape to exit edit mode.

Tool lock

When tool lock is enabled (via the toolbar or editor.updateInstanceState({ isToolLocked: true })), you can create multiple shapes without returning to the select tool after each one.

Shape properties

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, e.g. none, semi, solid, pattern
dashTLDefaultDashStyleStroke pattern: draw, solid, dashed, dotted, none
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
flipXbooleanMirror the shape horizontally
flipYbooleanMirror the shape vertically

Configuration options

Configure GeoShapeUtil to adjust rendering behavior:

OptionTypeDefaultDescription
showTextOutlinebooleantrueWhether to show a text outline (using the canvas background color) to improve label readability.
tsx
import { GeoShapeUtil } from 'tldraw'

const ConfiguredGeoUtil = GeoShapeUtil.configure({
	showTextOutline: false,
})

Pass the configured utility to the shapeUtils prop:

tsx
<Tldraw shapeUtils={[ConfiguredGeoUtil]} />

Custom geo types

Register custom geo types via customGeoTypes to add new forms without forking GeoShapeUtil. Custom types inherit all standard geo behavior (labels, fill/dash/color styling, resizing, SVG export, and hyperlinks) and provide their own path geometry, snap behavior, creation size, and style panel icon.

tsx
import { GeoShapeUtil, PathBuilder } from 'tldraw'

const MyGeoShapeUtil = GeoShapeUtil.configure({
	customGeoTypes: {
		'rounded-rect': {
			getPath: (w, h, shape, strokeWidth) => {
				const r = Math.min(w, h) * 0.2
				return new PathBuilder()
					.moveTo(r, 0, { geometry: { isFilled: shape.props.fill !== 'none' } })
					.lineTo(w - r, 0)
					.circularArcTo(r, false, true, w, r)
					.lineTo(w, h - r)
					.circularArcTo(r, false, true, w - r, h)
					.lineTo(r, h)
					.circularArcTo(r, false, true, 0, h - r)
					.lineTo(0, r)
					.circularArcTo(r, false, true, r, 0)
					.close()
			},
			snapType: 'polygon',
			icon: 'geo-rectangle',
			defaultSize: { w: 200, h: 150 },
		},
	},
})

Each entry in customGeoTypes is a GeoTypeDefinition. Keys that collide with a built-in form are ignored with a console warning.

FieldTypeDescription
getPath(w, h, shape, strokeWidth) => PathBuilderReturns the path geometry for this type at the given dimensions.
snapType'polygon' | 'blobby''polygon' snaps to vertices and center; 'blobby' snaps to center only.
iconstringIcon name used in the style panel's geo picker.
defaultSize{ w: number; h: number } (optional)Size used when the shape is created via click rather than drag. Defaults to 200 × 200.
onDoubleClick(shape) => { props } | void (optional)Custom double-click handler. Return a partial props update to mutate the shape, or nothing to no-op.

Custom types appear in the style panel's geo picker alongside the built-in shapes. See the custom geo types example for a full implementation.

Label positioning

The align and verticalAlign properties control where labels appear within the shape:

Horizontal alignment

ValuePosition
startLeft edge of shape
middleHorizontally centered
endRight edge of shape

Vertical alignment

ValuePosition
startTop of shape
middleVertically centered
endBottom of shape

When the label text exceeds the shape's height, the shape automatically grows by adding to growY. The shape never shrinks below its original h value to accommodate shorter text—instead, growY returns to 0.

Resizing behavior

Geo shapes resize from any corner or edge handle. When resizing a shape with a label:

  • The shape won't shrink smaller than the label's measured dimensions
  • growY resets to 0 when you resize, and the shape recalculates the needed height
  • Dragging a handle past the opposite edge flips the shape by toggling flipX or flipY

When you first add a label to a shape smaller than 51 × 51 unscaled pixels, the shape grows to at least that size and becomes square.

Special interactions

Rectangle/checkbox toggle

Double-click a rectangle while holding Alt to convert it to a checkbox. Double-click the checkbox with Alt held to convert it back to a rectangle. This lets you quickly add checkmarks to items.

Cloud shape variation

The cloud shape generates its bumps procedurally based on the shape's ID. Each cloud has unique bump positions, giving visual variety while maintaining a consistent style. Larger clouds have more bumps; smaller clouds have fewer but at least six.

Handle snap geometry

When you drag a line handle (or any custom handle with snapType set) near a geo shape, it snaps to the shape's outline. Polygon-based forms (rectangle, triangle, pentagon, and so on) also snap to each vertex and the center; curved forms (ellipse, oval, cloud, heart) snap only to the center. Arrow terminals bind to geo shapes through a separate system; see Bindings.

Dynamic resize mode

When dynamic resize mode is enabled in user preferences, new geo shapes scale inversely with zoom level. Drawing while zoomed out creates shapes that appear the same size on screen as they would at 100% zoom.

tsx
// Enable dynamic resize mode
editor.user.updateUserPreferences({ isDynamicSizeMode: true })

Geo shapes can link to URLs. When a shape has a URL, a link button appears on the shape:

tsx
editor.createShape({
	type: 'geo',
	x: 100,
	y: 100,
	props: {
		geo: 'rectangle',
		w: 200,
		h: 100,
		url: 'https://tldraw.dev',
	},
})

Click the link button to open the URL in a new tab.

Path rendering

Geo shapes use a path-based rendering system. Each geometric form, built-in or custom, has a GeoTypeDefinition whose getPath method generates the outline used for both fills and strokes. The same path drives solid, semi-transparent, and pattern fills as well as solid, dashed, and dotted stroke styles. Path calculations are cached per shape.

When the dash property is set to 'draw', the shape renders with organic, hand-drawn strokes. The randomness is seeded by the shape's ID, so each shape's hand-drawn look stays stable across renders.

Geometry

The shape's geometry returns a Group2d containing:

  1. The outline path geometry (polygon or curve depending on the form)
  2. A label rectangle for hit testing text interactions

The label rectangle is excluded from the shape's bounds but used for hit testing.

  • Default shapes — Overview of all built-in shapes
  • Rich text — Working with formatted text content
  • Styles — Working with shape styles like color and fill
  • Tools — How tools handle user input