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
169 lines
5.7 KiB
Plaintext
169 lines
5.7 KiB
Plaintext
---
|
|
title: Highlighting
|
|
created_at: 1/31/2026
|
|
updated_at: 1/31/2026
|
|
keywords:
|
|
- highlight
|
|
- hover
|
|
- hinting
|
|
- shape indicator
|
|
- visual feedback
|
|
- page state
|
|
- hoveredShapeId
|
|
- hintingShapeIds
|
|
status: published
|
|
date: 1/31/2026
|
|
---
|
|
|
|
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](/sdk-features/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.
|
|
|
|
## Related articles
|
|
|
|
- [Indicators](/sdk-features/indicators) — How indicator outlines are drawn and customized
|
|
- [Instance state](/sdk-features/instance-state) — Session state including page state
|
|
- [Selection](/sdk-features/selection) — Working with selected shapes
|
|
- [Cursors](/sdk-features/cursors) — Cursor types and customization
|
|
|
|
## API reference
|
|
|
|
| Method | Description |
|
|
| ------------------------------ | -------------------------------------- |
|
|
| [Editor#getHoveredShapeId](?) | Get the ID of the shape under pointer |
|
|
| [Editor#getHoveredShape](?) | Get the shape object under pointer |
|
|
| [Editor#setHoveredShape](?) | Manually set or clear hover state |
|
|
| [Editor#getHintingShapeIds](?) | Get IDs of shapes with hint indicators |
|
|
| [Editor#getHintingShape](?) | Get shapes with hint indicators |
|
|
| [Editor#setHintingShapes](?) | Set shapes to show hint indicators |
|