Open-Source Wikis

/

tldraw

/

Features

/

Shapes and tools

tldraw/tldraw

Shapes and tools

Active contributors: Steve Ruiz, Mime Čuvalo, Mitja Bezenšek

Purpose

How a user-visible "shape" actually exists in the codebase: as a record in the store, plus a ShapeUtil that defines how it renders and behaves, plus optionally a StateNode tool that creates and edits it.

The shape pipeline

graph LR
    Schema["TLShape record types"] -->|registered| Store
    Store -->|provides records| Editor
    ShapeUtils["ShapeUtil subclasses"] -->|registered| Editor
    Editor -->|render| Component[Shape component]
    Editor -->|geometry| Hit[hit-testing, snapping, selection]
    Editor -->|export| SVG[SVG export]
    User -->|drag| Tool[StateNode tool]
    Tool -->|editor.createShape| Editor
  1. Record type — declared in packages/tlschema/src/shapes/TL<Kind>Shape.ts. Defines props, validators, and migrations.
  2. Shape utilpackages/tldraw/src/lib/shapes/<kind>/<Kind>ShapeUtil.tsx extends ShapeUtil<TLKindShape> from packages/editor/src/lib/editor/shapes/ShapeUtil.ts. Implements component(), indicator(), getGeometry(), plus optional onResize, onTranslate, onHandleDrag, toSvg, etc.
  3. Toolpackages/tldraw/src/lib/tools/<Tool>/<Tool>.ts extends StateNode. The tool listens for pointer/keyboard, transitions through child states, and calls editor.createShape(...) and editor.updateShape(...).

Default set

The default shapes (packages/tldraw/src/lib/shapes/):

Shape Kind id Notes
Arrow arrow Curved/straight lines with binding endpoints.
Bookmark bookmark URL preview.
Draw draw Pressure-sensitive freehand.
Embed embed iframe embeds.
Frame frame Container with title and clipping.
Geo geo Rect/ellipse/triangle/diamond/star/etc.
Highlight highlight Highlighter strokes.
Image image Image with crop.
Line line Multi-point line.
Note note Sticky note.
Text text Text label.
Video video Video player.
Group group (Geometry-only; not a default tool.)

The default tools (packages/tldraw/src/lib/tools/):

  • SelectTool — the biggest. Manages selection, translation, resizing, rotation, cropping, brush selection, edit mode, label editing.
  • HandTool — pan camera.
  • EraserTool — erase shapes.
  • LaserTool — temporary laser pointer.
  • ZoomTool — zoom to box / +/-.
  • Per-shape tools wired in defaultShapeTools.ts: Draw, Arrow, Note, Text, Highlight, Frame, Geo, Line.

Shared selection logic — translating with snap, brushing, cropping, resizing — lives in packages/tldraw/src/lib/tools/selection-logic/.

Geometry

Every shape returns a Geometry2d from getGeometry(). The geometry library lives in packages/editor/src/lib/primitives/geometry/. It supports point-in-shape tests, segment intersection, bounds, padding, and SVG path output. The SpatialIndexManager indexes shape bounds with rbush so hit-testing is fast even with thousands of shapes.

Bindings

Some shapes have relationships with others. Arrow endpoints can be bound to shapes — when a shape moves, its bound arrows update. Binding records and the BindingUtil API live in packages/tlschema/src/bindings/ and packages/editor/src/lib/editor/bindings/. The default arrow uses a TLArrowBinding.

Custom shapes and tools

Templates demonstrate the pattern:

  • templates/agent/ — AI-driven shapes.
  • templates/shader/ — WebGL shaders inside shapes.
  • templates/workflow/ — node-based shape graph.

To add a custom shape to your app, define a RecordType (or use customRecordType), implement a ShapeUtil, and pass it via <Tldraw shapeUtils={[MyShapeUtil]} />.

Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.

Shapes and tools – tldraw wiki | Factory