Every static definition and dynamic chart builder resolves to a ChartSpec. The spec owns chart composition, scale factories or fixed scale instances, and presentation.
interface ChartSpec<TMarks extends readonly ChartMark[]> {
marks: TMarks
x: ChartAxisOptions | null
y: ChartAxisOptions | null
guides?: boolean
color?: ChartColorOptions
gradients?: readonly ChartLinearGradient[]
clip?: boolean
margin?: number | Partial<ChartMargin>
theme?: Partial<ChartTheme>
}| Property | Required | Meaning |
|---|---|---|
| marks | Yes | Ordered mark layers. Later scene nodes paint after earlier ones. |
| x | Yes | X scale and guide options, or null when no mark uses an x scale. |
| y | Yes | Y scale and guide options, or null when no mark uses a y scale. |
| guides | No | Set to false to suppress both axes, grid lines, titles, and their implicit margins. |
| color | No | Shared categorical or custom color scale and optional legend. |
| gradients | No | Linear-gradient resources consumed by the resource-aware SVG renderer. |
| clip | No | Clips the marks group to the resolved inner chart bounds when the selected renderer supports resources. |
| margin | No | Locks all margins with a number or selected sides with a partial object. Omitted sides are measured automatically. |
| theme | No | Overrides default foreground, muted, grid, background, or palette tokens. |
The detailed option contracts live in Scales, guides, and color. Mark-specific channels and defaults live in the mark reference.
marks is the grammar's composition unit:
import { areaY, defineChart, lineY, ruleY } from '@tanstack/charts'
import { scaleLinear, scaleUtc } from 'd3-scale'
const definition = defineChart({
marks: [
areaY(rows, { x: 'date', y: 'value', fillOpacity: 0.12 }),
ruleY([target], {
stroke: '#dc2626',
strokeWidth: 1.5,
strokeDasharray: '4 2',
}),
lineY(rows, { x: 'date', y: 'value', points: true }),
],
x: { scale: xScale },
y: { scale: yScale, grid: true },
})Each mark materializes channels for scale resolution, then emits renderer- neutral scene nodes and optional interaction points. Marks may use different datum types in the same spec. Their inferred datum types become a union in interaction callbacks.
Use stable key channels for data that reorders, enters, or exits. Mark IDs default from layer order; set id explicitly when a mark must retain identity while its order changes.
x and y are intentionally required. Supply a D3 factory for an inferred domain or a configured instance for a fixed domain:
const axes = {
x: { scale: scaleUtc },
y: { scale: scaleLinear },
}Use null only when that dimension has no materialized channel:
const horizontalThresholds = defineChart({
marks: [ruleY([25, 50, 75])],
x: null,
y: { scale: scaleLinear().domain([0, 100]) },
})guide: false hides an axis but does not remove its scale. x: null or y: null declares that no scale exists. Scene compilation throws when a mark materializes values for a missing positional scale.
Guide visibility and geometry are separate:
Automatic margins contain labels; they do not choose a collision policy. Control dense labels with the scale's tick behavior, ticks, format, or tickRotate.
clip and gradients are scene data. Render them with renderChartSvgWithResources:
import { renderChartSvgWithResources } from '@tanstack/charts/svg/resources'
const definition = defineChart({
marks,
x,
y,
clip: true,
gradients: [
{
id: 'revenue',
y1: 1,
y2: 0,
stops: [
{ offset: 0, color: '#2563eb', opacity: 0.08 },
{ offset: 1, color: '#2563eb', opacity: 0.72 },
],
},
],
})Reference a declared gradient from a mark paint as url(#revenue) and select the resource-aware renderer on the host or adapter. idPrefix scopes generated resource IDs when multiple charts share a document. See Rendering and export.
The complete default theme is exported as defaultChartTheme:
interface ChartTheme {
foreground: string
muted: string
grid: string
background: string
palette: readonly string[]
}theme is partial. The palette is replaced as one value rather than merged by index. The default palette uses CSS custom-property fallbacks:
.dashboard {
--ts-chart-1: #38bdf8;
--ts-chart-2: #fb7185;
--ts-chart-3: #4ade80;
}Because the default foreground and guide colors use currentColor, charts inherit light and dark mode without a JavaScript theme switch. Override theme tokens when the application needs an explicit visual system.