TanStack
Mark Reference

Sunburst Mark

sunburst partitions a flat hierarchy into nested angular sectors. It runs inside polar, so ring radii resolve from the final polar layout without application-owned partition rows or D3 arc generators.

ts
import { defineChart } from '@tanstack/charts'
import { sunburst } from '@tanstack/charts/hierarchy/sunburst'
import { polar } from '@tanstack/charts/polar'

const chart = defineChart({
  marks: [
    polar({
      startAngle: Math.PI / 2,
      endAngle: Math.PI / 2 - Math.PI * 2,
      marks: [
        sunburst(rows, {
          path: 'name',
          delimiter: '.',
          value: 'size',
          innerRadius: ({ radius }) => radius * 0.14,
          ringPadding: 2,
          color: 'branchId',
          stroke: '#fff',
        }),
      ],
    }),
  ],
})

The exact @tanstack/charts/hierarchy/sunburst subpath keeps hierarchy construction and partitioning out of root, universal, ordinary polar, and radial-bar consumers.

Hierarchy input

Path input constructs parent-child relationships from a string channel:

ts
sunburst(rows, {
  path: 'name',
  delimiter: '.',
  value: 'size',
})

Explicit parent references use nodeId because id identifies the mark:

ts
sunburst(rows, {
  id: 'package-sunburst',
  nodeId: 'id',
  parentId: 'parentId',
  value: 'size',
})

Path input may omit ancestors. Those structural nodes have data: null and empty direct lineage. Duplicate identities, invalid parents, multiple roots, and cycles throw before rendering. Source child order is preserved unless sort is supplied.

Path-mode node IDs use the shared hierarchy contract's canonical slash form, independent of the authored delimiter. The original row and path remain on data; use them when presentation must preserve source spelling. Path-mode name is the terminal path segment. Explicit-parent IDs are opaque, so their name is the complete authored ID even when it contains a slash.

Options

SunburstPathOptions<TDatum> and SunburstParentOptions<TDatum> form the SunburstOptions<TDatum> union.

OptionTypeDefaultMeaning
pathTransformValue<TDatum, string>Path mode onlyFull hierarchy path
delimiterstring/One-character path separator
nodeIdTransformValue<TDatum, string>Parent modeExplicit node identity
parentIdTransformValue<TDatum, string?>Parent modeExplicit parent identity
valueTransformValue<TDatum, number?>RequiredNonnegative contribution aggregated through parents
sortSunburstNodeComparator<TDatum>Source orderSibling comparator over immutable node values
innerRadiusPolarLength0Responsive inner edge of the first rendered ring
outerRadiusPolarLengthLayout radiusResponsive outer edge of the last rendered ring
ringPaddingnumber0Fixed CSS-pixel gap between hierarchy depths
id, classNamestringDerivedStable mark identity and optional class
zChannel<SunburstNode<TDatum>, ChartKey?>No groupGeometry and interaction group
colorChannel<SunburstNode<TDatum>, ChartKey?>zValue sent to the chart color scale
fill, strokeVisualChannel<SunburstNode<TDatum>, string>Color / nonePer-sector paint
fillOpacity, strokeOpacity, strokeWidthnumberRenderer valueSector presentation
strokeDasharraystringNoneSector stroke dash pattern
opacitynumberRenderer valueWhole-sector opacity
motionChartMarkMotionOptions<SunburstNode<TDatum>>['motion']NonePer-node motion policy

Nullish values contribute zero. Other values must be finite and nonnegative. ringPadding is a nonnegative pixel value. If padding consumes the available radial span, the mark omits sectors instead of emitting inverted rings.

Responsive partition

The enclosing polar mark owns the angular sweep and final center. sunburst allocates each node's angle from its aggregate value and divides the resolved innerRadius to outerRadius span into equal depth rings. The radius options accept pixel lengths or responsive callbacks through PolarLength. Both resolved radii must be finite and nonnegative; their order controls the ring direction.

ringPadding remains a fixed pixel gap as the chart resizes. It does not change the hierarchy values or angular allocation. Sectors replay the shared renderer-neutral D3 path commands into a sampled interaction polygon, so rounded, reversed, and complete sectors retain paint-faithful focus geometry.

Nodes and lineage

The root is structural and is not painted. Every rendered sector carries one SunburstNode<TDatum> with:

  • stable id, parentId, and root-to-parent ancestorIds;
  • name, depth, height, and internal / external metadata;
  • aggregate value;
  • branchId, equal to the first node below the root for that branch;
  • the direct authored data row, or null for an imputed node; and
  • direct source and sourceIndexes lineage.

branchId is useful for inherited branch color: color: 'branchId' gives a top-level branch and all its descendants one color without preparing a color field. Paint, motion, and sort callbacks receive the same immutable node values.

Types

The exact entry exports sunburst, SunburstNode, SunburstNodeComparator, SunburstPathOptions, SunburstParentOptions, and SunburstOptions.

See Polar Marks for angular sweeps and responsive PolarLength values.