Back to Tldraw

Highlighting

apps/docs/content/sdk-features/highlighting.mdx

5.4.05.4 KB
Original Source

Shape highlighting shows visual indicators on shapes to provide feedback during user interactions. The editor tracks two types of highlighting: hover (the shape under the pointer) and hints (shapes you want to emphasize programmatically).

tsx
import { Tldraw } from 'tldraw'
import 'tldraw/tldraw.css'

export default function App() {
	return (
		<div style={{ position: 'fixed', inset: 0 }}>
			<Tldraw
				onMount={(editor) => {
					// Highlight specific shapes with a visual indicator
					const shapes = editor.getCurrentPageShapes()
					if (shapes.length > 0) {
						editor.setHintingShapes([shapes[0]])
					}
				}}
			/>
		</div>
	)
}

Hover highlighting

The editor automatically tracks which shape is under the pointer and displays a selection-style indicator around it. Hovering a child of a group hovers the group, unless that group is focused or selected, in which case the child itself is hovered.

Reading hover state

Use Editor#getHoveredShapeId or Editor#getHoveredShape to check which shape is currently hovered:

typescript
// Get the hovered shape ID
const hoveredId = editor.getHoveredShapeId()

// Get the full shape object
const hoveredShape = editor.getHoveredShape()

if (hoveredShape) {
	console.log('Hovering over:', hoveredShape.type)
}

Setting hover manually

Use Editor#setHoveredShape to set the hover state yourself:

typescript
// Set hover by shape or ID
editor.setHoveredShape(myShape)
editor.setHoveredShape(myShape.id)

// Clear hover
editor.setHoveredShape(null)

The select tool overwrites this value on the next pointer move while it's idle or editing, so a manual hover only sticks inside your own tool or state. For programmatic emphasis, use hints instead.

Automatic hover detection

The select tool updates hover state as the pointer moves (throttled to 32ms, and paused while the camera is moving). The hover indicator appears when:

  • The select tool is in idle or editing_shape
  • The pointer is over the canvas (not UI elements)
  • The pointer is not coarse (touch, and pen on some devices)
  • The editor is not changing styles
  • The shape is not already selected

Touch devices don't show hover indicators because touch has no hovering concept.

Hint highlighting

Hints let you highlight multiple shapes programmatically. Unlike hover (single shape, automatic), hints are set explicitly and can include any number of shapes. The select tool uses them too: it hints the drop target during drag-and-drop and the shapes a new frame will enclose, so hints you set may be replaced while the user is dragging.

Reading hints

Use Editor#getHintingShapeIds or Editor#getHintingShape to get currently hinted shapes:

typescript
// Get array of hinted shape IDs
const hintedIds = editor.getHintingShapeIds()

// Get array of hinted shape objects
const hintedShapes = editor.getHintingShape()

Setting hints

Use Editor#setHintingShapes to highlight shapes:

typescript
// Highlight shapes by ID or shape object
editor.setHintingShapes([shape1, shape2])
editor.setHintingShapes([shape1.id, shape2.id])

// Clear all hints
editor.setHintingShapes([])

Hinted shapes render with a thicker stroke (2.5 screen pixels) than selected or hovered shapes (1.5). Setting hints never creates an undo entry, and ids are deduplicated on write.

For example, to hint the arrows bound to the selected shape, react to the selection:

typescript
import { react } from 'tldraw'

const stop = react('hint bound arrows', () => {
	const selected = editor.getOnlySelectedShape()
	if (selected) {
		const bindings = editor.getBindingsToShape(selected, 'arrow')
		editor.setHintingShapes(bindings.map((b) => b.fromId))
	} else {
		editor.setHintingShapes([])
	}
})

Visual rendering

Both hover and hint indicators use the theme's selection color. The ShapeIndicatorOverlayUtil strokes them on a canvas overlay using each shape's ShapeUtil#getIndicatorPath. Collaborator selections render at 1.5px in the collaborator's color at 0.7 opacity. See Indicators for the stroke widths and how to customize them.

Page state storage

Hover and hint state are stored in TLInstancePageState, which tracks per-page interaction state. Each page maintains its own hover and hint values.

typescript
const pageState = editor.getCurrentPageState()

pageState.hoveredShapeId // TLShapeId | null
pageState.hintingShapeIds // TLShapeId[]

Both properties are ephemeral—they don't persist across sessions or sync between collaborators.

  • Indicators — How indicator outlines are drawn and customized
  • Instance state — Session state including page state
  • Selection — Working with selected shapes
  • Cursors — Cursor types and customization

API reference

MethodDescription
Editor#getHoveredShapeIdGet the ID of the shape under pointer
Editor#getHoveredShapeGet the shape object under pointer
Editor#setHoveredShapeManually set or clear hover state
Editor#getHintingShapeIdsGet IDs of shapes with hint indicators
Editor#getHintingShapeGet shapes with hint indicators
Editor#setHintingShapesSet shapes to show hint indicators