Files
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

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 |