Files
upstream-tldraw/apps/docs/content/sdk-features/arrow-shape.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

161 lines
8.1 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
title: Arrow shape
created_at: 1/31/2026
updated_at: 1/31/2026
keywords:
- arrow
- connector
- binding
- elbow
- arc
- arrowhead
status: draft
date: 1/31/2026
---
The arrow shape draws a connector between two points on the canvas. Arrows can bind to other shapes, so they stay attached when those shapes move. Arrows route as curved arcs or right-angled elbows, take one of nine arrowhead styles at each end, and can carry a rich text label.
## Creating arrows
An arrow is a shape of type `arrow`. Its `start` and `end` props are points relative to the shape's position:
```tsx
import { Tldraw, toRichText } from 'tldraw'
import 'tldraw/tldraw.css'
export default function App() {
return (
<div style={{ position: 'fixed', inset: 0 }}>
<Tldraw
onMount={(editor) => {
editor.createShape({
type: 'arrow',
x: 100,
y: 100,
props: {
start: { x: 0, y: 0 },
end: { x: 300, y: 100 },
richText: toRichText('connects to'),
},
})
}}
/>
</div>
)
}
```
The full set of props on [TLArrowShape](?):
| Property | Type | Description |
| ---------------- | ---------------------------- | ----------------------------------------------------- |
| `kind` | `TLArrowShapeKind` | Routing mode: `arc` (default) or `elbow` |
| `start` | `VecModel` | Start terminal position, relative to the shape origin |
| `end` | `VecModel` | End terminal position |
| `bend` | `number` | Curvature for arc arrows (`0` = straight) |
| `elbowMidPoint` | `number` | Position (0–1) of the middle segment for elbow arrows |
| `color` | `TLDefaultColorStyle` | Stroke color |
| `fill` | `TLDefaultFillStyle` | Fill style for arrowheads |
| `dash` | `TLDefaultDashStyle` | Stroke pattern |
| `size` | `TLDefaultSizeStyle` | Stroke width preset |
| `arrowheadStart` | `TLArrowShapeArrowheadStyle` | Arrowhead at the start (default `none`) |
| `arrowheadEnd` | `TLArrowShapeArrowheadStyle` | Arrowhead at the end (default `arrow`) |
| `richText` | `TLRichText` | Optional text label |
| `labelPosition` | `number` | Label position along the arrow (0 = start, 1 = end) |
| `labelColor` | `TLDefaultColorStyle` | Label text color |
| `font` | `TLDefaultFontStyle` | Font family for the label |
| `scale` | `number` | Scale factor applied to the shape |
## Binding arrows to shapes
When a user draws an arrow onto a shape, the editor creates an arrow binding: a record that connects one of the arrow's terminals to the target shape. The arrow recalculates its path whenever the bound shape moves, resizes, or rotates. When a terminal is bound, the editor computes its position from the binding and ignores the corresponding `start` or `end` prop.
To bind an arrow programmatically, create a binding of type `arrow` from the arrow to the target shape:
```tsx
editor.createBinding({
type: 'arrow',
fromId: arrow.id,
toId: targetShape.id,
props: {
terminal: 'end',
normalizedAnchor: { x: 0.5, y: 0.5 },
isPrecise: false,
isExact: false,
snap: 'none',
},
})
```
An arrow can have up to two bindings, one with `terminal: 'start'` and one with `terminal: 'end'`. Use [getArrowBindings](?) to read an arrow's current bindings. See [Bindings](/sdk-features/bindings) for how bindings work in general, and the [create arrow example](https://github.com/tldraw/tldraw/tree/main/apps/examples/src/examples/editor-api/create-arrow) for a complete implementation.
### Precise and exact bindings
Three binding props control where the arrow attaches. See [TLArrowBindingProps](?) for details.
| Prop | Effect |
| ------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `normalizedAnchor` | The attachment point within the shape's bounds, where `{ x: 0, y: 0 }` is the top-left corner and `{ x: 1, y: 1 }` is the bottom-right |
| `isPrecise` | When `true`, the arrow points at the `normalizedAnchor` position. When `false`, it points at the shape's center |
| `isExact` | When `true`, the arrowhead travels all the way to the anchor point, entering the shape. When `false`, the arrow stops at the edge of the shape's geometry |
When drawing with the arrow tool, users get imprecise center bindings by default. Hovering over a spot inside a shape for a moment, pausing while dragging a terminal, or holding Alt switches to a precise binding at that spot. The `hoverPreciseTimeout` and `pointingPreciseTimeout` options control the delays, and holding Ctrl skips binding entirely (`shouldIgnoreTargets`).
## Routing: arc and elbow
The `kind` prop selects between the two routing modes. It's a style prop, so users can switch modes from the style panel.
Arc arrows (`kind: 'arc'`, the default) draw a straight line or a circular arc between their terminals. The `bend` prop is the perpendicular distance from the straight line to the arc's midpoint: `0` draws a straight line, positive and negative values curve to either side. Users adjust the bend by dragging the arrow's middle handle.
Elbow arrows (`kind: 'elbow'`) route with right-angled segments, like connectors in a flowchart. The `elbowMidPoint` prop (0–1) positions the middle segment between the two ends. The binding's `snap` prop records what the terminal snapped to when drawn: `'center'`, `'edge'`, `'edge-point'`, or `'none'`. The edge values are only produced for elbow arrows, which use them when routing.
## Arrowheads
The `arrowheadStart` and `arrowheadEnd` props set the style of each end independently. The available styles are `arrow`, `triangle`, `square`, `dot`, `pipe`, `diamond`, `inverted`, `bar`, and `none`. By default, arrows have `none` at the start and `arrow` at the end.
```tsx
editor.updateShape({
id: arrow.id,
type: 'arrow',
props: {
arrowheadStart: 'dot',
arrowheadEnd: 'triangle',
},
})
```
## Labels
Arrows can have a rich text label, stored in the `richText` prop. Use [toRichText](?) to create one from a plain string. The `labelPosition` prop (0–1) places the label along the arrow's path, with `0.5` (the default) at the midpoint. Users can drag the label along the arrow to reposition it. The `labelColor` and `font` props style the label's text.
## Configuration
[ArrowShapeUtil](?) exposes options for tuning arrow behavior, like snap distances, precise-targeting timeouts, and whether new arrows bind exactly. Use the static `configure` method to override them:
```tsx
import { ArrowShapeUtil, Tldraw } from 'tldraw'
import 'tldraw/tldraw.css'
const shapeUtils = [
ArrowShapeUtil.configure({
// Precise arrows point exactly at the spot the user picked
shouldBeExact: (editor, isPrecise) => isPrecise,
}),
]
export default function App() {
return (
<div style={{ position: 'fixed', inset: 0 }}>
<Tldraw shapeUtils={shapeUtils} />
</div>
)
}
```
See [ArrowShapeOptions](?) for the full list of options.
## Related examples
- [Create arrow](https://github.com/tldraw/tldraw/tree/main/apps/examples/src/examples/editor-api/create-arrow) — Create an arrow between two shapes programmatically, including both bindings.
- [Precise and exact arrows](https://github.com/tldraw/tldraw/tree/main/apps/examples/src/examples/configuration/arrows-precise-exact) — Configure the arrow tool so precise targets produce exact bindings.