Indicators

Indicators are the outlines that appear around shapes when they're selected or hovered. They provide visual feedback about which shapes are active. They also help users understand the bounds of each shape.

How indicators work

When you select a shape in tldraw, an indicator appears as a stroke around the shape's geometry. Indicators are separate from the shape's visual appearance so they can be styled consistently across all shape types.

Each ShapeUtil defines how its indicator should be drawn by implementing the required getIndicatorPath method:

import { HTMLContainer, Rectangle2d, ShapeUtil } from 'tldraw'

class CardShapeUtil extends ShapeUtil<CardShape> {
	static override type = 'card'

	getDefaultProps(): CardShape['props'] {
		return { w: 100, h: 100 }
	}

	getGeometry(shape: CardShape) {
		return new Rectangle2d({
			width: shape.props.w,
			height: shape.props.h,
			isFilled: true,
		})
	}

	component(shape: CardShape) {
		return <HTMLContainer>Hello</HTMLContainer>
	}

	getIndicatorPath(shape: CardShape) {
		const path = new Path2D()
		path.rect(0, 0, shape.props.w, shape.props.h)
		return path
	}
}

The getIndicatorPath method returns paths in the shape's local coordinate space. The editor automatically positions and styles these paths based on selection state.

When indicators appear

By default, indicators appear in these situations:

StateDescription
SelectedThe shape is in the current selection
HoveredThe pointer is over the shape (desktop only, not touch)
HintingThe shape is being referenced during an operation

Indicators are hidden during certain interactions, like when changing styles or during tool operations that would make indicators distracting.

Defining paths

For most shapes, return a Path2D:

class MyShapeUtil extends ShapeUtil<MyShape> {
	override getIndicatorPath(shape: MyShape): Path2D | undefined {
		const path = new Path2D()
		path.rect(0, 0, shape.props.w, shape.props.h)
		return path
	}
}

Indicators are drawn on a single canvas layer, which is efficient when many shapes are selected.

Complex canvas indicators

For indicators that need clipping or multiple paths (like arrows with labels), return an object instead of a plain Path2D:

override getIndicatorPath(shape: MyShape): TLIndicatorPath | undefined {
	const bodyPath = new Path2D()
	bodyPath.moveTo(0, 0)
	bodyPath.lineTo(100, 100)

	const arrowheadPath = new Path2D()
	arrowheadPath.moveTo(90, 95)
	arrowheadPath.lineTo(100, 100)
	arrowheadPath.lineTo(95, 90)

	const labelClipPath = new Path2D()
	labelClipPath.rect(40, 40, 20, 20)

	return {
		path: bodyPath,
		clipPath: labelClipPath, // Areas to exclude from the main path
		additionalPaths: [arrowheadPath], // Extra paths to stroke
	}
}

Collaborator indicators

In multiplayer sessions, indicators show other users' selections. These appear with the collaborator's assigned color and slightly reduced opacity. The canvas indicator system handles collaborator indicators automatically.

TopicDescription
ShapesCreating custom shapes with ShapeUtil
User interfaceCustomizing tldraw's UI components
Custom indicators exampleWorking example of indicator customization
Prev
Assets
Next
Collaboration