TanStack logo

Skill

ship-accessible-charts

ship accessible TanStack Charts

Covers Accessibility Charts TanStack Frontend

Description

Ship TanStack Charts with meaningful accessibility, deterministic SSR and hydration, correct adapter lifecycle, renderer and export choices, exact package subpaths, and explicit React Native validation.

SKILL.md

Ship Accessible Charts

Run trigger → inspect → decide → build → verify before release. A chart is shipped only when its semantic alternative, adapter lifecycle, SSR policy, renderer, exports, package boundaries, and teardown are proven in a consumer-shaped scenario.

Accessibility Checks

Check: the name identifies the comparison

Expected:

const hostOptions = {
  definition,
  height: 320,
  initialWidth: 640,
  ariaLabel: 'Weekly downloads for Core and React packages',
  ariaDescription: 'Values are seven-day totals. Missing weeks appear as gaps.',
}

Fail condition: the label says only “chart”, repeats a visible heading without the metric, or omits the comparison and period.

Fix: name the metric, compared entities, and time scope; put conclusions and detailed values in normal application content.

Check: critical values have an equivalent representation

Expected: a visible heading and units, plus an adjacent summary or semantic table when precise values or application decisions depend on the chart.

Fail condition: the only way to retrieve an essential value is pointer hover, color, motion, or visual estimation.

Fix: bind the same semantic rows or selected key to application text/table controls.

Check: every interaction has a non-pointer path

Expected: native point keyboard navigation, semantic buttons/inputs for free cursors and range controls, visible focus, cancel/reset paths, and meaningful committed-state text.

Fail condition: a transparent pointer overlay is the sole control surface.

Fix: use first-party controls where their keyboard contract fits and application-owned semantic controls otherwise.

Lifecycle Checks

Check: SSR uses a supported adapter and deterministic inputs

Expected:

import {
  createChartRuntime,
  defineChart,
  lineY,
  renderChartSvg,
} from '@tanstack/charts'
import { scaleLinear } from '@tanstack/charts/scales/linear'
import { scaleUtc } from 'd3-scale'

interface TrafficRow {
  date: Date
  visits: number
}

const rows: readonly TrafficRow[] = [
  { date: new Date('2026-08-10T00:00:00Z'), visits: 820 },
  { date: new Date('2026-08-11T00:00:00Z'), visits: 910 },
]

const definition = defineChart({
  marks: [lineY(rows, { x: 'date', y: 'visits' })],
  x: { scale: scaleUtc },
  y: { scale: scaleLinear },
})

const runtime = createChartRuntime<TrafficRow, Date, number>()
const scene = runtime.render(definition, { width: 720, height: 400 })

export const svg = renderChartSvg(scene, {
  ariaLabel: 'Daily traffic',
  idPrefix: 'daily-traffic',
})

runtime.destroy()

Fail condition: definition construction reads browser layout, random values, local time, or unresolved async data; or the selected adapter does not promise SSR.

Fix: resolve data before render, use deterministic formatting and dimensions, and follow the selected adapter reference.

Check: mount, update, and cleanup stay adapter-owned

Expected: one runtime per mounted adapter instance, complete immutable option updates, stable definitions until captured values change, and cleanup on unmount/disconnect.

Fail condition: application code calls DOM measurement or mounts a browser host during server render, or retains observers/listeners after removal.

Fix: use the adapter lifecycle or mountChart only in a browser-owned mount phase and call destroy() at teardown.

Renderer and Export Checks

Check: renderer choice matches the task

  • SVG: visible server geometry, vector export, DOM styling, ordinary interactive charts.
  • Canvas: high scene counts or raster-first output; server emits an accessible shell, not pixels.
  • Static SVG: deterministic server/export artifact without browser interaction.
  • React Native SVG: explicit native target with device-level validation.

Check: export is reproducible

Expected: explicit dimensions, theme/background, scoped IDs, portable fonts/assets, intentional focus inclusion, and a meaningful exported name/description.

Fail condition: export depends on current responsive pixels or unreachable application CSS/resources.

Fix: render an explicit scene or serialize/rasterize with explicit artifact policy.

Common Mistakes

CRITICAL Using a generic accessible label

Wrong: ariaLabel: 'Chart'.

Correct: identify the metric, entities, period, and unit needed to understand the figure.

A generic label exposes a focusable graphic without useful identity.

Source: docs/guides/accessibility.md

HIGH Making the chart the only representation

Wrong: require hover or visual estimation for exact operational values.

Correct: render a summary, table, or application controls from the same semantic data/state.

The chart surface is supplemental when exact values are critical.

Source: docs/guides/accessibility.md; archived responsive/accessibility notes

CRITICAL Mounting a browser host during server rendering

Wrong: call mountChart or adapter DOM mount from a server lifecycle.

Correct: prerender a deterministic scene through a supported SSR adapter or renderChartSvg, then mount the browser host only after a real element exists.

Measurement and mutation require browser elements. Older Angular workarounds were especially prone to this boundary error.

Source: GitHub issue 56; docs/guides/ssr-and-hydration.md

HIGH Putting behavior on adapter props

Wrong:

<Chart definition={chart} tooltip keyboard />

Correct:

const interactive = defineChart(chart, { tooltip, keyboard: true })
<Chart definition={interactive} ariaLabel="Revenue by month" />

Focus, tooltip, keyboard, controls, cursors, and SVG animation belong to the reusable definition; adapters own surface lifecycle and framework body composition. The current definition API replaces legacy adapter behavior props.

Source: chart-behavior migration in CHANGELOG.md; React chart reference

HIGH Importing the universal barrel on native

Wrong: use @tanstack/charts/universal for every native chart.

Correct: use exact core mark/scale/scene and @tanstack/charts/react-native subpaths unless cross-platform authoring justifies the universal bundle.

Exact imports protect Metro and native declaration environments from unrelated browser and optional capability code.

Source: API-FRICTION.md F-154, F-171, F-173, F-256; React Native package README

HIGH Tension: rich interaction versus portable rendering

DOM convenience can break static SVG, Canvas, native, SSR, or keyboard equivalence. Keep semantics in definitions and application state; use platform-specific body/host extensions only at the presentation seam.

See also: build-chart-interactions/SKILL.md and extend-tanstack-charts/SKILL.md

Pre-Deploy Summary

  • Meaningful name and concise description.
  • Visible units, time range, and source context.
  • Exact-value summary/table where required.
  • Pointer, keyboard, touch, and cancel/reset scenarios.
  • Reduced-motion and non-color evidence.
  • Supported SSR policy with deterministic initial geometry.
  • Stable definition, mark, datum, and resource IDs.
  • Mount, update, resize, font relayout, and destroy verified.
  • Renderer and export behavior verified from a packed consumer.
  • Native claims verified on target devices when applicable.

References

See also: debug-and-verify-charts/SKILL.md — SSR, accessibility, renderer, and package claims need consumer-level evidence.

© 2026 YourAI.tools. Every skill from an identity-verified publisher.

Independent catalog. Not affiliated with, endorsed by, or sponsored by Anthropic or any listed publisher. All trademarks belong to their respective owners.