---
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 (
{
editor.createShape({
type: 'arrow',
x: 100,
y: 100,
props: {
start: { x: 0, y: 0 },
end: { x: 300, y: 100 },
richText: toRichText('connects to'),
},
})
}}
/>
)
}
```
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 (
)
}
```
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.