Skip to content

TanStack Charts v0.0.1

Choose a tag to compare

@github-actions github-actions released this 31 Jul 00:22
· 313 commits to main since this release
Immutable release. Only release title and notes can be modified.
15dcb15

Changelog

0.0.1 (2026-07-30)

0.0.1 is the first coordinated update after the public 0.0.0 release. The
verified 0.0.0 baseline is
58ee1e28e469f8ab28f99877a6e0abc3958977a4, not the initial repository
commit.

  • npm published @tanstack/charts@0.0.0 at
    2026-07-29T18:42:40Z, followed through 18:43:13Z by the React, Octane,
    Preact, Vue, Solid, Svelte, Angular, Lit, and Alpine adapters.
  • The published core and React README hashes, and the published core
    chart-definitions documentation hash, match commit 58ee1e2 exactly.
  • No later commit existed before those packages were published.

The audited product implementation range ends at
a91106c34d654ea625a2f540f647222bd72bc0fc and contains exactly nine
commits. Release-preparation corrections in this branch update the
documentation, comparison fixture and baseline, and this changelog after that
implementation range.

Compare the audited product range.

Release scope and gates

  • 0.0.1 publishes @tanstack/charts and the React, Octane, Preact, Vue,
    Solid, Svelte, Angular, Lit, and Alpine adapters as one versioned set. Every
    adapter depends exactly on @tanstack/charts@0.0.1.
  • The comparison bundle review confirmed that basic TanStack line, bar, area,
    and scatter consumers now measure 24.19–24.81 KiB gzip. The increase comes
    from the reviewed definition-behavior, key-inference, scale-inference, and
    portal-tooltip code rather than an accidental dependency. The comparison
    fixture now configures behavior on the definition instead of the removed
    host boundary, and the refreshed baseline passed the full pull-request
    validation, comparison, conformance, and stress workflow.
  • The tanstack.com schema-v4 catalog consumer must be deployed and verified
    before the Charts release reaches main, because the successful main-branch
    workflow publishes the schema-v4 artifact to catalog-dist. Keep schema-v2
    compatibility until the production catalog and embed routes are verified.
  • The release commit must pass the same package, documentation, bundle,
    comparison, catalog, stress, and conformance gates before its tag, GitHub
    release, and npm provenance identify that exact revision.
  • @charts-poc/demo-data remains private. It is a catalog, example, and
    validation fixture package, not a production dependency or release target.
  • @tanstack/charts-d3 remains a private superseded experiment and is not a
    release target.

Package impact

All product packages in this table already existed at the published baseline.
This range updates them; it does not introduce new adapters.

Package 0.0.1 update
@tanstack/charts Definition-owned reactivity and behavior, inferred keys and scale domains, portal tooltips, typed data
@tanstack/react-charts Updated definition contract, composed tooltip bodies, portal mounting, and a react-dom peer
@tanstack/octane-charts Updated definition contract across SVG, Canvas, and renderer entries, plus composed tooltip bodies
@tanstack/preact-charts Updated definition contract, SVG adoption behavior, and composed tooltip bodies
@tanstack/vue-charts Updated definition contract, SSR forwarding fixes, and a scoped tooltip-body slot
@tanstack/solid-charts Updated definition contract, stable SSR IDs, and composed tooltip bodies
@tanstack/svelte-charts Updated definition contract, hydration behavior, and a tooltip-body snippet
@tanstack/angular-charts Updated definition contract and a typed projected tooltip template directive
@tanstack/lit-charts Updated definition contract and composed tooltip rendering through options
@tanstack/alpine-charts Updated definition contract and DOM tooltip-body rendering

Breaking changes and migrations

Definition identity is now the application reactivity boundary

The runtime no longer accepts formal chart input, prepares data, or compares
input values. A definition captures the application values it uses. Recreate
or memoize the complete definition when those values change. A responsive
builder still reruns when its surface size or build-time theme changes.

Before:

const definition = defineChart<readonly Row[]>()({
  prepare: (rows) => summarize(rows),
  prepareEqual: Object.is,
  inputEqual: Object.is,
  chart: ({ input, prepared, width, height, theme }) => ({
    marks: createMarks(input, prepared),
    x: createXScale(width),
    y: createYScale(height, theme),
  }),
})

<Chart definition={definition} input={rows} ariaLabel="Revenue" />

After:

function createRevenueDefinition(rows: readonly Row[]) {
  const prepared = summarize(rows)

  return defineChart({
    marks: createMarks(rows, prepared),
    x: { scale: scaleUtc, nice: true },
    y: { scale: scaleLinear, nice: true },
  })
}

const definition = useMemo(() => createRevenueDefinition(rows), [rows])

<Chart definition={definition} ariaLabel="Revenue" />

Migration details:

  • Remove input from DOM-host and framework-adapter options.
  • Move transforms beside defineChart, or into the framework memo or computed
    primitive that creates the definition.
  • Replace prepare, prepareEqual, and inputEqual. Prepared-data caching
    and the preparation AbortSignal no longer exist.
  • Remove uses of ChartPrepareContext, chartInputsEqual, and
    shallowInputEqual.
  • Replace StaticChartHostOptions, DynamicChartHostOptions,
    StaticChartProps, and DynamicChartProps with the unified host and adapter
    contracts.
  • Read only width, height, and theme from ChartBuildContext.
  • Call runtime.render(definition, size, layout?); the runtime no longer
    accepts an input argument.
  • Update low-level generic arguments. ChartDefinition,
    DynamicChartDefinition, ChartRuntime, hosts, adapters, and points now
    describe datum, x-value, and y-value types rather than input and
    prepared-data types.
  • For vanilla updates, create the next definition and pass it through
    host.update.
  • For framework updates, memoize the complete definition against every
    application value it captures.

DynamicChartConfig remains public. It combines a responsive
chart(context) builder with definition-owned behavior options.

Chart behavior moved from hosts into definitions

Focus, tooltip, animation, keyboard, focus-distance, and spatial-index policy
are reusable chart behavior. Hosts and framework components no longer accept
focus, maxFocusDistance, spatialIndex, animate, keyboard, or
tooltip.

Before:

<Chart
  definition={definition}
  focus={focusX}
  tooltip={{ sticky: true }}
  animate={{ duration: 180 }}
  keyboard
  ariaLabel="Revenue"
/>

After:

const interactiveDefinition = defineChart(definition, {
  focus: 'nearest-x',
  tooltip: true,
  animate: { duration: 180 },
  keyboard: true,
})

<Chart definition={interactiveDefinition} ariaLabel="Revenue" />

Static definitions may declare behavior directly. Responsive definitions place
behavior beside chart. defineChart(existingDefinition, options) creates a
separately configured definition without moving surface policy back into the
adapter.

The host still owns:

  • dimensions and aspect ratio;
  • accessible labels and descriptions;
  • surface class names and styles;
  • focus, grouped-focus, selection, render, and tooltip-body callbacks;
  • text measurement;
  • renderer selection.

The focus option now accepts nearest, nearest-x, nearest-y, group-x,
and group-y, as well as a custom focus strategy.

Enabled tooltips are pinnable by default. Click, Enter, or Space pins the
current tooltip; Escape or a composed body's dismiss callback clears it. Set
tooltip: { sticky: false } for transient-only behavior.

Resize animation is opt-in

ChartAnimationOptions.resize now defaults to false.

  • Definition changes may still animate.
  • Responsive observation and explicit size changes commit immediately unless
    animate.resize is true.
  • Incompatible layout changes never interpolate.
  • Interrupted animations still begin from currently painted geometry.
  • Renderer completion is associated with the render reason so an older
    animation cannot overwrite a newer immediate resize.

Applications that deliberately animate size changes must opt in:

const definition = defineChart(chart, {
  animate: {
    duration: 180,
    resize: true,
  },
})

Built-in marks infer stable identity

Built-in marks no longer fall back immediately to row index. Identity resolves
in this order:

  1. An explicit key
  2. A unique primitive datum.id
  3. A unique primitive datum.data.id
  4. A unique mark-specific positional candidate
  5. Row index

Mark-specific candidates:

  • bars use their categorical channel;
  • lines and areas use their independent axis;
  • rects and cells use the complete x/y interval tuple;
  • dots and text try x, then y, then the x/y tuple;
  • polar lines, areas, and rules use angle;
  • D3 pie-backed polar arcs can recover nested source identity.

A candidate must be complete and unique inside its interaction group.
Development builds warn once per mark instance when a positional candidate is
missing or duplicated and identity falls back to row position.

Remove redundant keys when an ID or semantic position already identifies the
datum. Keep an explicit key when position can change independently of entity
identity. Use key: (_datum, index) => index only when positional identity is
intentional.

D3 scale factories now request domain inference

Positional, color, radius, and polar scale options distinguish a factory from
a configured instance.

const inferred = {
  x: { scale: scaleUtc, nice: true },
  y: { scale: scaleLinear, nice: true },
}

const configured = {
  x: { scale: scaleUtc().domain(fixedDateDomain) },
  y: { scale: scaleLinear().domain([0, fixedMaximum]) },
}

Migration rules:

  • Pass scaleLinear, scaleUtc, or another zero-argument D3 factory when the
    domain should follow mark channels.
  • Use a wrapper such as () => scaleBand<string>().padding(0.2) when the
    factory needs pre-domain configuration.
  • Continue passing a configured D3 instance when the application owns a fixed
    domain.
  • Do not pass scaleLinear() and expect data inference. It is a configured
    instance and retains D3's default domain until the application changes it.
  • Move nicening for inferred axes to nice?: boolean | number.
  • Keep every granular d3-* module imported by application source as a direct
    application dependency.

Inference behavior:

  • continuous and temporal axes use the finite extent of every materialized
    channel on that axis;
  • band and point axes retain distinct values in first-seen order;
  • implicit bar and area baselines contribute zero;
  • empty channels retain the scale factory's native domain;
  • configured instances are copied and never mutated;
  • TanStack Charts owns responsive ranges, y orientation, reversal, band
    centering, guide layout, and final tick placement.

Validation is stricter:

  • inferred quantitative and temporal scales reject incompatible semantic
    values instead of coercing them;
  • an inferred log domain rejects zero or a domain that crosses zero;
  • a bar or area with an implicit zero baseline cannot use an inferred log
    scale;
  • required-axis checks follow each mark's materialized dimensions;
  • configuring an unused phantom axis is rejected.

Color factories now infer ordinal, continuous, quantize, quantile, or threshold
domains and expose semantic scale kind and thresholds to legends. Radius
factories infer [0, maximum] while preserving configured output ranges.
Polar angle and radius scales use the same factory-versus-instance contract.

Point and scale types are more precise

  • ChartPoint.xValue and yValue preserve inferred Date, numeric, or
    categorical values.
  • ChartMarkPointX and ChartMarkPointY describe interaction anchors.
  • ChartMarkScaleX and ChartMarkScaleY describe values materialized into
    scales.
  • ChartMarkX and ChartMarkY remain deprecated compatibility aliases.
  • Rectangle and cell interval scale values are independent from their
    interaction anchors.
  • Custom marks whose interaction and scale values differ use
    createMarkWithScaleValues from @tanstack/charts/mark/scale-values.
  • Positionless polar and geo definitions may omit Cartesian axes.
  • A one-dimensional mark requires only the dimension it materializes.

Core updates

Channel, interval, and layout refinements

  • Added an independent semantic color channel across existing Cartesian,
    polar, and geographic marks.
  • z remains geometry and interaction grouping. It is the color fallback when
    color is omitted.
  • For lines and areas, color groups paths only when z is absent. When both
    exist, z groups geometry and color supplies scale semantics.
  • Grouped bars use z, or color when no z is present.
  • Final fill and stroke accessors remain paint overrides.
  • Interaction-point colors now match the fill or stroke actually painted.
  • Interval points now expose x1Value, x2Value, y1Value, y2Value, and
    xInterval or yInterval range and difference semantics.
  • Channel field types reject datum fields incompatible with the mark channel.
  • Inference carries datum and coordinate types through focus, tooltip,
    spatial-index, selection, adapter, and renderer callbacks.
  • Custom marks may provide layoutLabels, allowing data-bound labels,
    including polar and geographic labels, to contribute to automatic margins.

Tooltip, focus, and interaction refinements

The native tooltip model now provides structured content rather than only
plain text:

  • safe titles;
  • ordered rows and swatches;
  • channel and datum items;
  • derived items;
  • interval ranges and differences;
  • content, items, sort, anchor, placement, and offset options;
  • compatibility with existing format and formatGroup callbacks.

Grouped tooltip rows can sort by color-domain order, focus order, or a custom
comparator. Anchors can follow the point, pointer, group center, or a custom
coordinate. Eight placements and ordered fallbacks support viewport collision
handling.

tooltip.portal moves the native surface out of clipped stacking contexts.
The host uses the browser Popover top layer when available and a fixed
body-level fallback otherwise. Both paths:

  • map scene anchors to client coordinates;
  • collide against the viewport;
  • reposition on scroll, viewport resize, chart resize, and tooltip-content
    resize;
  • target the chart's owner document;
  • clean up when the definition, renderer, or chart host changes.

Framework adapters can compose native framework content into the core-owned
tooltip body. The body context contains points, structured content,
defaultBody, pinned, and dismiss. Transient custom bodies remain inert;
pinned bodies become nonmodal dialogs and may contain selectable or
interactive content.

The renderer-neutral host exposes onTooltipBodyChange and
ChartTooltipBodyTarget for lower-level integrations.

Additional interaction corrections:

  • duplicate public keys no longer collapse distinct observations during path
    hover or responsive repaint;
  • spatial-index option changes repaint active focus and tooltip state.

Framework adapter updates

Every existing adapter moved to the definition-identity update contract and
removed formal input and host-owned behavior props. Callback types continue to
infer from the complete definition, and committed callbacks remain fresh
without forcing a new definition.

  • Shared adapter prerendering preserves className; Vue declares and forwards
    it on both server and client paths.

Adapter-specific tooltip composition:

  • React, Octane, Preact, and Solid expose renderTooltipBody.
  • Vue exposes a scoped #tooltipBody slot.
  • Svelte exposes a tooltipBody snippet.
  • Angular exports ChartTooltipBodyDirective, with the definition as its
    strict type witness.
  • Lit accepts options.renderTooltipBody.
  • Alpine accepts renderTooltipBody returning DOM content.

React now declares react-dom ^19.0.0 as a peer because composed tooltip bodies
use React portals. React and Octane preserve the existing default SVG,
/canvas, and renderer-neutral /core entry boundaries.

Catalog, demo data, and publication artifact

The catalog already contained 100 cases at the published 0.0.0 baseline.
This range changes the data and publication model without claiming a catalog
count expansion.

Source-shaped demo data

  • Added the private @charts-poc/demo-data workspace package with 27 pinned
    Observable datasets and a metadata subpath.
  • Every dataset has an exact subpath export and records source URL, upstream
    revision, record count, schema, byte size, license note, and SHA-256.
  • Small snapshots are emitted as typed rows.
  • Large CSV snapshots remain compact and parse only when their exact subpath is
    imported. Sibling datasets and the CSV parser stay out of unrelated chunks.
  • All 100 existing catalog cases were migrated away from case-local data.ts
    fixtures and now import source-shaped data through exact subpaths.
  • Case selection, sampling, joins, derived channels, normalization, layout, and
    transforms remain visible in selection.ts, transform.ts, layout.ts, or
    model modules.
  • Only two authored interaction-state fixtures remain. They are explicitly
    named scenario.ts, not observation data.
  • React, Octane, and sandbox showcases now use pinned source-shaped datasets
    instead of synthetic Stats-shaped fixtures.
  • Demo data is externalized from renderer bundle measurement and is not a
    production dependency of any Charts package.
  • Deterministic sync, metadata, schema, hash, exact-subpath, and compact-CSV
    tests cover the package.

Schema-v4 source and asset closures

The existing generated-content publication pipeline now emits a schema-v4
catalog artifact.

  • The artifact records the exact Charts revision, source repository, route and
    embed contracts, renderer module contract, implementation counts, datasets,
    authored-source metadata, and asset graph.
  • Each case records TanStack and reference source closures by entry, support,
    fixture, and harness role.
  • Authored-source totals include transitive implementation and transform code
    while excluding harness code and raw dataset rows.
  • Published modules are recursively allowlisted with SHA-256, byte size, static
    imports, and dynamic imports.
  • Validation rejects unsafe paths, oversized or unreferenced assets,
    inconsistent closures, and public comparison modules.
  • The catalog source viewer exposes the same closure and dataset provenance
    used by artifact validation.
  • Loading checks preserve the existing contract: the normal catalog and embed
    routes load only TanStack code; competitor code remains opt-in.

The artifact cannot replace the production schema-v2 feed until tanstack.com
has deployed and verified its schema-v4 consumer.

Documentation, comparison, and lineage

Lineage

  • Acknowledgements now distinguish implementation lineage from conceptual
    lineage.
  • Public concepts, overview, and marketing material credit the
    grammar-of-graphics tradition and its development through Leland Wilkinson,
    ggplot2, Vega-Lite, and Observable Plot.
  • Observable Plot remains identified as the closest API influence for
    mark-local data, channels, and layered composition.

Public documentation gaps

  • Expanded the existing canonical documentation from 71 to 81 pages.
  • Added the evidence-backed comparison page.
  • Added missing framework adapter references and completed renderer,
    controller, scale, color, tooltip, and public-type contracts.
  • Documented definition identity, framework memoization, inferred stable keys,
    D3 factory ownership, inferred domains, structured and portaled tooltips,
    point-versus-scale types, SSR, hydration, and migration requirements.
  • Corrected shared SSR className forwarding and documented the exact adapter
    support boundary.

Documentation validation now:

  • parses typed code fences;
  • resolves TanStack imports through package manifests;
  • verifies named value and type imports against the selected public entry;
  • checks local heading fragments, including duplicate-heading suffixes;
  • rejects name-only API inventories as reference coverage;
  • typechecks designated standalone examples;
  • compiles the Octane quick start in client and server modes;
  • verifies generated package docs and both llms.txt indexes remain in sync.

Reproducible comparison evidence

  • The public comparison is generated from shared capability evidence rather
    than a handwritten feature matrix.
  • Bundle evidence covers Chart.js 4.5.1, Apache ECharts 6.1.0, Recharts
    3.10.1, Observable Plot 0.6.17, and TanStack Charts across line, bar,
    area, and scatter at basic, interactive, and advanced tiers.
  • Source accounting follows each implementation's transitive authored closure
    and keeps dataset provenance separate from authored chart code.
  • The current baseline records the reviewed 24.19–28.20 KiB complete-chart
    range. Pull-request CI reproduced the bundle and comparison gates before the
    release version was prepared.

Verification added or updated in the audited product range

  • Runtime, host, renderer, and framework tests cover definition identity,
    behavior ownership, resize render reasons, animation interruption, key
    inference, duplicate-key focus, tooltip pinning, portal placement, and
    cleanup.
  • Type-contract tests cover mark channels, point and scale value separation,
    required axes, factory inference, configured instances, callback inference,
    and adapter props.
  • Scale tests cover quantitative, temporal, band, point, log, color, radius,
    and polar inference, including empty and invalid domains.
  • Packed-consumer tests cover the revised core, DOM, React, Octane, and adapter
    declaration contracts without casts or private imports.
  • Documentation checks cover 81 canonical pages, executable examples, public
    package entries, exports, links, and generated mirrors.
  • Catalog checks cover all 100 cases, source roles, exact dataset subpaths,
    schema-v4 asset closures, source-view parity, and TanStack-only production
    loading.
  • The full catalog and interaction evidence completed during this range.

0.0.1 release-preparation corrections

  • Updated the canonical docs, public READMEs, generated package mirrors, and
    llms.txt indexes for the 0.0.1 API.
  • Replaced temporary unreleased-source warnings with 0.0.1 installation
    guidance, including the React DOM runtime and type peers required by the
    React adapter.
  • Replaced private demo-data imports in public examples with small,
    self-contained typed datasets.
  • Fixed the comparison fixture to configure behavior on definitions instead of
    the removed host boundary.
  • Refreshed the reviewed bundle baseline and recorded the TanStack workspace
    revision separately from pinned competitor package versions.
  • Updated the offline chart-authoring evaluation to target the 0.0.1
    definition, behavior, and scale contracts.
  • Added this baseline-verified changelog and the required tanstack.com
    consumer-before-catalog deployment order.

Audited product commit inventory

  1. 9d23a50 (2026-07-29), Credit grammar-of-graphics lineage:
    clarified implementation and conceptual lineage across acknowledgements,
    concepts, overview, and marketing.
  2. d2c4d44 (2026-07-29), Close public documentation gaps:
    expanded the canonical reference, added evidence-backed comparison content,
    tightened documentation contracts, and fixed public host, focus, export,
    scale, and adapter gaps discovered while documenting the API.
  3. dc4bc70 (2026-07-29), Make definition identity the chart reactivity
    boundary
    : removed formal input, preparation, equality, and cache APIs and
    migrated runtimes, hosts, adapters, examples, and all catalog cases to
    captured application values.
  4. 235455f (2026-07-29), Disable chart animation during resize:
    classified render reasons, made responsive and explicit resize immediate by
    default, and added animate.resize opt-in.
  5. b9e1886 (2026-07-29), Move chart behavior into definitions:
    moved focus, tooltip, animation, keyboard, focus distance, and spatial
    indexing out of hosts; added focus presets, pinnable tooltips, and richer
    structured tooltip behavior.
  6. f07fdf2 (2026-07-29), Infer stable chart keys:
    added ID and mark-specific positional identity inference, development
    diagnostics, and reconciliation, animation, and focus coverage.
  7. de65652 (2026-07-29), Infer scale domains from marks:
    added direct D3 factories, domain inference, axis nicening, strict value
    validation, and corresponding positional, color, radius, and polar scale
    behavior.
  8. 4b940ed (2026-07-30), Add composable portal tooltips:
    added top-layer and fixed portal positioning, framework-native tooltip
    bodies, pinned dialog behavior, and adapter-specific composition APIs.
  9. a91106c (2026-07-30), Improve chart inference and catalog data:
    completed point and scale typing, required-axis inference, independent color
    channels, interval metadata, source-shaped demo data, visible transform
    roles, source closures, and the schema-v4 catalog artifact.