TanStack logo

Skill

configure-scales-guides-color

configure scales and guides for TanStack Charts

Covers Data Visualization Charts TanStack Frontend

Description

Configure TanStack Charts domains, scale factories, axes, margins, legends, grouping, and paint without taking ownership of responsive ranges. Load for blank geometry, scale inference, color semantics, shared domains, ticks, labels, or guide layout.

SKILL.md

Configure Scales, Guides, and Color

Use trigger → inspect → decide → build → verify. The application owns semantic domains and color policy; TanStack Charts owns inferred domains, responsive positional ranges, guide measurement, and final paint resolution.

Setup

Use factories for inferred domains and configured instances for fixed semantic domains:

import { colorLegend, defineChart, lineY } from '@tanstack/charts'
import { scaleLinear } from '@tanstack/charts/scales/linear'
import { scaleOrdinal } from '@tanstack/charts/scales/ordinal'
import { scalePoint } from '@tanstack/charts/scales/point'

const rows = [
  { week: 'May 4', package: 'core', downloads: 820 },
  { week: 'May 11', package: 'core', downloads: 960 },
  { week: 'May 4', package: 'react', downloads: 610 },
  { week: 'May 11', package: 'react', downloads: 730 },
]

const color = scaleOrdinal<string, string>()
  .domain(['core', 'react'])
  .range(['#2563eb', '#f97316'])

export const chart = defineChart({
  marks: [lineY(rows, { x: 'week', y: 'downloads', z: 'package' })],
  x: { scale: () => scalePoint<string>().padding(0.2) },
  y: {
    scale: scaleLinear,
    nice: true,
    grid: true,
    axis: { label: 'Downloads' },
  },
  color: { scale: color, legend: colorLegend({ label: 'Package' }) },
})

Core Patterns

Choose a scale by semantics

  • Numeric position → compact scaleLinear.
  • Categories with width → compact scaleBand.
  • Categories without width → compact scalePoint.
  • Stable categorical paint → compact scaleOrdinal.
  • Elapsed time, nonlinear transforms, radial mapping, statistical bins, or continuous color → exact d3-scale family.

Read the ownership matrix before configuring a D3 instance.

Share domains intentionally

import { scaleLinear } from '@tanstack/charts/scales/linear'

export const percentScale = scaleLinear().domain([0, 1])

export const sharedPercentAxis = {
  scale: percentScale,
  axis: {
    label: 'Conversion rate',
    ticks: { format: (value: number) => `${Math.round(value * 100)}%` },
  },
}

A configured instance keeps the domain stable across filtering, facets, or linked views. Charts copies it and assigns the current range.

Keep series identity separate from paint

import { lineY } from '@tanstack/charts'

const rows = [
  { date: '2026-08-01', series: 'api', status: 'healthy', value: 91 },
  { date: '2026-08-01', series: 'worker', status: 'healthy', value: 84 },
]

export const mark = lineY(rows, {
  x: 'date',
  y: 'value',
  z: 'series',
  color: 'status',
})

Use z for geometry groups, color for semantic scale values, and fill/stroke for final local paint overrides.

Separate tick candidates from label collision

Tick count, spacing, or values chooses candidates. Label thinning, rotation, formatting, and priority decide which candidate labels remain readable. Automatic margins contain guides; they do not make every label legible.

Common Mistakes

CRITICAL Assigning positional pixel ranges

Wrong:

x: {
  scale: scaleLinear().range([0, 640])
}

Correct:

x: {
  scale: scaleLinear
}

The final plot range changes after container measurement and guide margins resolve.

Source: API-FRICTION.md F-002; docs/concepts/scales-and-d3.md

CRITICAL Using a default instance for inference

Wrong:

y: {
  scale: scaleLinear()
}

Correct:

y: {
  scale: scaleLinear
}

A scale instance owns its domain; the factory delegates domain inference to chart channels.

Source: CHANGELOG.md 0.0.1 migration; docs/concepts/scales-and-d3.md

HIGH Using color as geometry identity accidentally

Wrong:

lineY(rows, { x: 'date', y: 'value', color: 'status' })

Correct:

lineY(rows, {
  x: 'date',
  y: 'value',
  z: 'series',
  color: 'status',
})

When z is absent, a discrete color channel can also partition connected geometry.

Source: API-FRICTION.md F-009, F-013; docs/concepts/data-and-channels.md

HIGH Treating containment as collision avoidance

Wrong: rely on automatic margins to solve dense tick labels.

Correct: define candidate spacing, thinning priority, rotation, abbreviation, or a different responsive composition.

Margins keep guides inside the surface; they do not guarantee labels avoid each other.

Source: API-FRICTION.md F-023, F-160; docs/guides/responsive-charts.md

HIGH Tension: responsive adaptation versus comparison stability

Reduce labels or change composition at narrow widths, but do not silently change a shared domain, threshold, or category-color assignment to make the chart fit.

See also: design-responsive-charts/SKILL.md § Common Mistakes

References

See also: design-responsive-charts/SKILL.md and debug-and-verify-charts/SKILL.md — final ranges depend on layout, and blank charts often expose scale-contract failures.

© 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.