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:
| State | Description |
|---|---|
| Selected | The shape is in the current selection |
| Hovered | The pointer is over the shape (desktop only, not touch) |
| Hinting | The 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.
Related topics
| Topic | Description |
|---|---|
| Shapes | Creating custom shapes with ShapeUtil |
| User interface | Customizing tldraw's UI components |
| Custom indicators example | Working example of indicator customization |