These marks cover reference lines, independent segments, directed relationships, fixed-pixel vectors, and compact glyphs. They compose with any other mark and use the chart's shared positional and color scales.
import {
arrow,
link,
ruleX,
ruleY,
tickX,
tickY,
vector,
} from '@tanstack/charts'ruleX draws a vertical rule through the complete inner chart height. ruleY draws a horizontal rule through the complete inner chart width.
ruleX(events, { x: 'date', stroke: '#dc2626' })
ruleY([0], { strokeOpacity: 0.7, strokeDasharray: '4 2' })function ruleX<TDatum>(
source: Iterable<TDatum>,
options?: RuleXOptions<TDatum>,
): ChartMark<never, InferredX, never>
function ruleY<TDatum>(
source: Iterable<TDatum>,
options?: RuleYOptions<TDatum>,
): ChartMark<never, never, InferredY>Options are orientation-specific:
| Option | Type | Default | Meaning |
|---|---|---|---|
| id | string | Layer-derived | Stable mark ID |
| x | Channel<TDatum, ChartValue?> | Datum itself when it is a chart value | ruleX position |
| y | Channel<TDatum, ChartValue?> | Datum itself when it is a chart value | ruleY position |
| stroke | string | Theme foreground | Constant stroke |
| strokeOpacity | number | 0.5 | Stroke opacity |
| strokeWidth | number | SVG default | Stroke width |
| strokeDasharray | string | None | SVG dash array |
Rules emit no interaction points and therefore do not participate in native focus or tooltips. Their datum type is intentionally absent from the chart's interaction union.
link draws one independent segment per row. It is appropriate for networks, slopegraphs, error intervals, and annotations. Use lineY when consecutive rows form one path.
link(edges, {
x1: 'sourceX',
y1: 'sourceY',
x2: 'targetX',
y2: 'targetY',
z: 'kind',
key: 'id',
})function link<TDatum>(
source: Iterable<TDatum>,
options: LinkOptions<TDatum>,
): ChartMark<TDatum, InferredEndpointX, InferredEndpointY>| Option | Type | Default | Meaning |
|---|---|---|---|
| id | string | Layer-derived | Stable mark ID |
| x1, y1 | required channels | — | First endpoint |
| x2, y2 | required channels | — | Second endpoint |
| z | Channel<TDatum, ChartKey?> | No group | Interaction group and default stroke color |
| key | Channel<TDatum, ChartKey> | Unique id, then index | Stable identity |
| stroke | VisualChannel<TDatum, string> | Resolved z color | Segment stroke |
| strokeOpacity | number | SVG default | Stroke opacity |
| strokeWidth | number | 1.5 | Stroke width |
| strokeDasharray | string | None | SVG dash array |
| curve | ChartCurve | Straight rule | Optional path generator |
With no curve, the scene contains a rule. With a curve, it contains a two-point polyline with the generated path. The interaction coordinate is the pixel midpoint; semantic xValue and yValue are the second endpoint.
The optional d3Curve bridge and granular algorithm boundary are documented in Line and area and Scales and D3.
arrow draws one straight directed segment with a fixed-pixel head:
arrow(edges, {
x1: 'sourceX',
y1: 'sourceY',
x2: 'targetX',
y2: 'targetY',
headLength: 10,
headAngle: 28,
})function arrow<TDatum>(
source: Iterable<TDatum>,
options: ArrowOptions<TDatum>,
): ChartMark<TDatum, InferredEndpointX, InferredEndpointY>| Option | Type | Default | Meaning |
|---|---|---|---|
| id | string | Layer-derived | Stable mark ID |
| x1, y1 | required channels | — | Tail endpoint |
| x2, y2 | required channels | — | Head endpoint |
| z | Channel<TDatum, ChartKey?> | No group | Interaction group and default stroke |
| key | Channel<TDatum, ChartKey> | Unique id, then index | Stable identity |
| stroke | VisualChannel<TDatum, string> | Resolved z color | Arrow stroke |
| strokeOpacity | number | SVG default | Stroke opacity |
| strokeWidth | number | 1.5 | Stroke width |
| headLength | number | 8 | Head length in pixels, clamped to at least zero |
| headAngle | number | 30 | Half-angle in degrees |
The arrowhead stays the same pixel size as scales and container dimensions change. The interaction coordinate and semantic x/y values are the head endpoint.
vector places a fixed-pixel directed vector at a scaled anchor:
vector(wind, {
x: 'longitude',
y: 'latitude',
length: 'speed',
rotate: 'bearing',
anchor: 'middle',
z: 'region',
})function vector<TDatum>(
source: Iterable<TDatum>,
options: VectorOptions<TDatum>,
): ChartMark<TDatum, InferredX, InferredY>| Option | Type | Default | Meaning |
|---|---|---|---|
| id | string | Layer-derived | Stable mark ID |
| x, y | required channels | — | Scaled anchor |
| length | number | Channel<TDatum, number?> | 12 | Vector length in pixels |
| rotate | number | Channel<TDatum, number?> | 0 | Clockwise degrees; zero points up |
| anchor | 'start' | 'middle' | 'end' | 'middle' | Which vector position stays at x/y |
| z | Channel<TDatum, ChartKey?> | No group | Interaction group and default stroke |
| key | Channel<TDatum, ChartKey> | Unique id, then index | Stable identity |
| stroke | VisualChannel<TDatum, string> | Resolved z color | Stroke |
| strokeOpacity | number | SVG default | Stroke opacity |
| strokeWidth | number | 1.5 | Stroke width |
| headLength | number | 5 | Head length in pixels, clamped to at least zero |
| headAngle | number | 30 | Head half-angle in degrees |
Length and rotation must be finite. Negative length reverses the body direction while preserving the rotation convention. The interaction point remains the scaled x/y anchor for every anchor mode.
Ticks draw a short rule centered at a scaled point:
tickX(rows, { x: 'category', y: 'value', z: 'series' })
tickY(rows, { x: 'value', y: 'category', length: 16 })function tickX<TDatum>(
source: Iterable<TDatum>,
options: TickXOptions<TDatum>,
): ChartMark<TDatum, InferredX, InferredY>
function tickY<TDatum>(
source: Iterable<TDatum>,
options: TickYOptions<TDatum>,
): ChartMark<TDatum, InferredX, InferredY>Both share:
| Option | Type | Default | Meaning |
|---|---|---|---|
| id | string | Layer-derived | Stable mark ID |
| x, y | required channels | — | Tick center |
| z | Channel<TDatum, ChartKey?> | No group | Interaction group and default stroke |
| key | Channel<TDatum, ChartKey> | Unique id, then index | Stable identity |
| stroke | VisualChannel<TDatum, string> | Resolved z color | Tick stroke |
| strokeOpacity | number | SVG default | Stroke opacity |
| strokeWidth | number | 1.5 | Stroke width |
| length | number | Perpendicular scale bandwidth, otherwise 6 | Total length before inset |
| inset | number | 0 | Pixels removed from both ends |
Available length is clamped to at least zero after subtracting twice the inset. Each valid row emits one interaction point at the tick center.
Links, arrows, vectors, and ticks skip rows with any invalid required positional value. Links and arrows require all four endpoints. Stable key channels are especially important for independent segments because keyed reconciliation otherwise falls back to row index.