
Skill
compose-marks-and-views
compose marks and views in TanStack Charts
Description
Translate semantic encodings into TanStack Charts marks, layers, annotations, facets, and coordinated views. Load when choosing marks, combining layers, assigning interaction-point ownership, or deciding whether a custom mark is justified.
SKILL.md
Compose Marks and Views
Use trigger → inspect → decide → build → verify. A chart type is usually a composition of marks with shared scales, not a component to look up by name.
Setup
Layer broad context first and direct evidence last:
import { areaY, defineChart, dot, lineY, ruleY, text } from '@tanstack/charts'
import { scaleLinear } from '@tanstack/charts/scales/linear'
import { scalePoint } from '@tanstack/charts/scales/point'
const rows = [
{ month: 'Jan', low: 72, value: 80, high: 89, label: '' },
{ month: 'Feb', low: 77, value: 86, high: 96, label: '' },
{ month: 'Mar', low: 84, value: 94, high: 106, label: 'Launch' },
]
export const chart = defineChart({
marks: [
areaY(rows, { id: 'range', x: 'month', y1: 'low', y2: 'high' }),
ruleY([90], { id: 'target' }),
lineY(rows, { id: 'trend', x: 'month', y: 'value' }),
dot(
rows.filter((row) => row.label),
{ id: 'events', x: 'month', y: 'value' },
),
text(
rows.filter((row) => row.label),
{
id: 'event-labels',
x: 'month',
y: 'value',
text: 'label',
dy: -10,
},
),
],
x: { scale: scalePoint },
y: { scale: scaleLinear },
})
Declaration order is paint order. Each mark may use a different datum type.
Core Patterns
Give one layer interaction ownership
import { defineChart, dot, lineY } from '@tanstack/charts'
import { decorative } from '@tanstack/charts/mark/decorative'
const rows = [
{ id: 'jan', month: 'Jan', value: 80 },
{ id: 'feb', month: 'Feb', value: 86 },
]
export const chart = defineChart({
marks: [
decorative(lineY(rows, { x: 'month', y: 'value' })),
dot(rows, { x: 'month', y: 'value', key: 'id' }),
],
})
decorative keeps geometry and scale materialization but removes duplicate focus, tooltip, and activation points.
Use explicit geometry groups
import { lineY } from '@tanstack/charts'
const rows = [
{ date: '2026-08-01', region: 'North', value: 42, status: 'healthy' },
{ date: '2026-08-01', region: 'South', value: 37, status: 'healthy' },
]
export const lines = lineY(rows, {
x: 'date',
y: 'value',
z: 'region',
color: 'status',
})
Keep geometry identity (z) separate from paint semantics (color) when they differ.
Choose the smallest complete composition
Escalate in this order:
- One built-in or first-party composite mark.
- Several built-in marks sharing scales.
- Facets or named views.
- D3-prepared rows passed to built-in marks.
compositeMarkbuilt from ordinary marks.- A custom mark that emits renderer-neutral scene nodes.
- An application-owned overlay or gesture controller.
Read the mark-selection matrix before creating a custom mark.
Use facets for repeated questions, views for distinct roles
Use facetChart when every panel asks the same question over a group. Use composeViews for focus-and-context, marginal summaries, or panels with distinct roles. Keep semantic shared state in the application; do not synchronize views through DOM nodes.
Common Mistakes
CRITICAL Encoding the chart as one custom path
Wrong: emit one path containing the complete visualization.
Correct: retain mark-local data, channels, scales, and interaction points; extend only the geometry that built-ins cannot express.
A monolithic path discards automatic domains, typed rows, portable rendering, focus ownership, and composability.
Source: docs/concepts/grammar-of-graphics.md; docs/guides/custom-marks-and-renderers.md
MEDIUM Expecting an area to draw its line
Wrong:
marks: [areaY(rows, { x: 'date', y: 'value' })]
Correct:
marks: [
areaY(rows, { x: 'date', y: 'value' }),
lineY(rows, { x: 'date', y: 'value' }),
]
Area and line are independent layers with independent style, state, and point ownership.
Source: docs/reference/marks/line-and-area.md
HIGH Letting decorative layers own duplicate points
Wrong: layer line, area, dots, and labels over the same rows with every mark interactive.
Correct: choose the semantic owner and wrap always-painted supporting marks with decorative.
Duplicate points create repeated keyboard stops, focus candidates, and tooltip rows.
Source: API-FRICTION.md F-218; docs/guides/tooltips-and-focus.md
HIGH Rebuilding supported coordinates in userland
Wrong: project polar, spatial, hierarchy, or network geometry into arbitrary pixels before chart layout.
Correct: use first-party coordinate/layout primitives, or a resolved-layout mark when final bounds are truly required.
Userland projection hides responsive final-bounds work and duplicates capability modules. Current first-party primitives fixed many early gaps, but old examples still encourage application-owned engines.
Source: API-FRICTION.md F-117, F-199–F-208; docs/examples/index.md
References
See also: build-chart-interactions/SKILL.md and extend-tanstack-charts/SKILL.md — layering determines point ownership, and native composition should be exhausted before extension.
More skills from the charts repository
View all 12 skillsbuild-chart-interactions
build chart interactions with TanStack Charts
Aug 15ChartsFrontendInteractionTanStackconfigure-scales-guides-color
configure scales and guides for TanStack Charts
Aug 15ChartsData VisualizationFrontendTanStackcoordinate-charts-with-tanstack
coordinate TanStack Charts with data sources
Aug 15ChartsData AnalysisData EngineeringFrontend +1debug-and-verify-charts
debug and verify TanStack Charts
Aug 15ChartsDebuggingFrontendTanStackdesign-a-chart
design charts with TanStack Charts
Aug 15ChartsData VisualizationFrontendTanStackdesign-responsive-charts
design responsive TanStack Charts
Aug 15ChartsData VisualizationFrontendSSR +1
More from TanStack
View publisheraggregation
perform data aggregation in TanStack Table
table
Aug 11Data AnalysisFrontendTanStackapi-not-found
diagnose TanStack Table API errors
table
Aug 11DebuggingFrontendTanStackcell-selection
select rectangular cell ranges in tables
table
Aug 11Data AnalysisTanStackUI Componentscell-spanning
configure cell spanning in TanStack Table
table
Aug 11Data VisualizationFrontendTanStackUI Componentsclient-vs-server
manage TanStack Table data pipelines
table
Aug 11Data PipelineFrontendPerformanceTanStackcolumn-faceting
build faceted filter UIs
table
Aug 11Data VisualizationFrontendTanStack