Files
upstream-tldraw/apps/docs/content/docs/indicators.mdx
upstream-mirror a774ac673a
Some checks failed
Deploy analytics worker / Deploy analytics worker to ${{ (github.ref == 'refs/heads/production' && 'production') || (github.ref == 'refs/heads/main' && 'staging') || 'preview' }} (push) Failing after 1s
i18n upload strings / Upload latest strings (push) Failing after 1s
Deploy bemo / Deploy bemo to ${{ (github.ref == 'refs/heads/bemo-production' && 'production') || (github.ref == 'refs/heads/main' && 'staging') || 'preview' }} (push) Failing after 1s
Deploy grafana resources / ${{ github.event_name == 'push' && 'Deploy grafana resources' || 'Validate grafana resources (dry run)' }} (push) Failing after 0s
End to end tests (dotcom) / Check for relevant changes (push) Failing after 0s
End to end tests (examples) / Check for relevant changes (push) Failing after 0s
End to end tests (mermaid readability) / Check for relevant changes (push) Failing after 1s
End to end tests (perf) / Check for relevant changes (push) Failing after 0s
Publish editor extensions / Publish editor extensions (push) Failing after 1s
Publish SDK packages / Remove the publish-packages label (push) Has been skipped
Checks / Tests & checks (push) Has been cancelled
Checks / Build all projects (push) Has been cancelled
Deploy templates / Deploy templates (push) Has been cancelled
End to end tests (dotcom) / End to end tests (dotcom) (push) Has been cancelled
End to end tests (mermaid readability) / End to end tests (mermaid readability) (push) Has been cancelled
End to end tests (perf) / End to end tests (perf) (push) Has been cancelled
Deploy .com / Deploy dotcom to ${{ (github.ref == 'refs/heads/production' && 'production') || (github.ref == 'refs/heads/main' && 'staging') || 'preview' }} (push) Has been cancelled
End to end tests (examples) / End to end tests (examples) (push) Has been cancelled
Publish SDK packages / Publish SDK packages (push) Has been cancelled
Publish SDK packages / Tell user released version (push) Has been cancelled
Publish SDK packages / Publishes code templates to separate repositories (push) Has been cancelled
Publish SDK packages / Deploys the template demos with the new SDK version (push) Has been cancelled
snapshot of https://github.com/tldraw/tldraw.git (main, 2026-09-23; blobs > 131072B omitted)
2026-09-23 16:12:52 +05:00

96 lines
3.9 KiB
Plaintext

---
title: Indicators
status: published
author: steveruizok
date: 3/22/2023
order: 5
keywords:
- indicators
- selection
- hover
- ShapeUtil
- custom shapes
---
Indicators are the outlines that appear around shapes when they're selected or hovered.
## How indicators work
Indicators are drawn on a canvas overlay in the theme's selection color, separate from the shape's own rendering. Each [ShapeUtil](?) defines its indicator by implementing the required [ShapeUtil#getIndicatorPath](?) method. It returns a `Path2D` in the shape's local coordinate space; the [ShapeIndicatorOverlayUtil](?) included with `<Tldraw>` transforms it into page space and strokes it. Return `undefined` to draw no indicator for a shape.
```tsx
class CardShapeUtil extends ShapeUtil<CardShape> {
// ...
getIndicatorPath(shape: CardShape) {
const path = new Path2D()
path.rect(0, 0, shape.props.w, shape.props.h)
return path
}
}
```
For shapes with more complex outlines, build the path from the shape's geometry:
```tsx
getIndicatorPath(shape: MyShape) {
return new Path2D(this.editor.getShapeGeometry(shape).toSimpleSvgPath())
}
```
See [Shapes](/docs/shapes) for the rest of the ShapeUtil.
## When indicators appear
The select tool shows indicators in these situations:
| State | Description |
| -------- | ------------------------------------------------------------------------------------------------------------------ |
| Selected | The shape is in the current selection |
| Hovered | The pointer is over the shape while the select tool is idle or editing a shape (fine pointers only, not touch) |
| Hinting | The shape is in [Editor#getHintingShapeIds](?), set with [Editor#setHintingShapes](?); drawn with a thicker stroke |
Indicators are hidden while the user is changing styles, while another tool is active, and for locked shapes.
All plain `Path2D` indicators are batched into a single stroke call, so many selected shapes stay cheap to draw.
## Complex canvas indicators
For indicators that need clipping or multiple paths (like arrows with labels), return a [TLIndicatorPath](?) object instead of a plain `Path2D`. The `clipPath` is applied as an even-odd clip region before stroking `path`, so to cut a hole for a label, add an outer rectangle plus the label rectangle. `additionalPaths` are stroked afterwards without the clip:
```tsx
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)
// Even-odd: the outer rect keeps everything, the inner rect punches a hole
const clipPath = new Path2D()
clipPath.rect(-100, -100, 300, 300)
clipPath.rect(40, 40, 20, 20)
return {
path: bodyPath,
clipPath,
additionalPaths: [arrowheadPath],
}
}
```
## Collaborator indicators
In multiplayer sessions, [CollaboratorShapeIndicatorOverlayUtil](?) draws other users' selections in each collaborator's color at reduced opacity, underneath the local indicators.
## Related topics
| Topic | Description |
| ---------------------------------------------------------- | ------------------------------------------------------------------- |
| [Shapes](/docs/shapes) | Creating custom shapes with ShapeUtil |
| [User interface](/docs/user-interface) | Customizing tldraw's UI components |
| [Custom indicators example](/examples/ui/indicators-logic) | Subclass `ShapeIndicatorOverlayUtil` to change when indicators show |