Hacktoberfest 2026: the issues maintainers tagged for October, open and beginner-friendly. Browse Hacktoberfest issues

Reconciler removes host-added attributes; cartesian marks lack a documented class hook

Open
#196 0 comments 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 1 day

Nobody has claimed this yet.

Assessment

Difficulty
4/5
Estimated time
3-5 days
Newbie friendliness
25/100
Issue type
Bug
Clarity
Mostly clear
Activity status
Active
Tech stack
typescript

Research direction

Start with the failing repro in packages/charts-core/test-repro/11-renderer-dom.test.ts and the syncAttributes removal loop in src/reconcile.ts (around lines 165-167); the animated path is in src/motion.ts (around lines 2204-2214), and focus layers re-render near line 1209. Done means the repro passes on both paths, with the design choice (reserved prefix versus a preserveAttributes option) settled by maintainers first. Part B, the missing className option on cartesian marks, is a separate docs-and-options change.

Written by the indexing model from the issue text.

Description

An app cannot keep its own per-node state (a data-* marker, a CSS custom property) on renderer nodes, because the reconciler strips it on the next rebuild. Cartesian marks also have no documented class hook.

A. Reconciler removes host-added attributes

  • syncAttributes runs for every retained element and removes each attribute the next scene element does not emit, including style, data-* and class: reconcile.ts:165-167.
  • The animated path does the same, exempting only data-ts-motion-role, transform and opacity: motion.ts:2204-2214.
  • Focus layers are re-rendered through the same reconciler on each focus change, so a host write there is lost: motion.ts:1209-1211.
  • The docs mention data-ts-key matching but not host attributes: rendering-and-export.md:130.

Repro: packages/charts-core/test-repro/11-renderer-dom.test.ts (vitest + jsdom)

import { expect, it } from 'vitest'
import { reconcileChartSvg } from '../src/reconcile'

const svg = (extra = '') =>
  `<svg xmlns="http://www.w3.org/2000/svg"><circle data-ts-key="a" class="ts-chart__dot" cx="1" cy="1" r="2"${extra}/></svg>`

it('keeps host-added attributes on a retained node across a rebuild', () => {
  const container = document.createElement('div')
  reconcileChartSvg(container, svg())
  const node = container.querySelector('circle')!
  node.setAttribute('data-x-active', '1')
  node.style.setProperty('--x-glow', '1')

  reconcileChartSvg(container, svg(' cx="5"')) // same key, cx changes

  expect(container.querySelector('circle')).toBe(node) // node is retained
  expect(node.getAttribute('data-x-active')).toBe('1')
  expect(node.style.getPropertyValue('--x-glow')).toBe('1')
})

Actual (pnpm vitest run packages/charts-core/test-repro/11-renderer-dom.test.ts): AssertionError: expected null to be '1' at the data-x-active assertion. The test covers the non-animated reconciler only.

Expected: attributes the scene never emits (a documented prefix such as data-x-*, or custom properties inside style) are left alone on retained nodes. Preferred: skip removal for a reserved prefix in both syncAttributes loops. Alternative: a reconcile.preserveAttributes: string[] host option.

B. Cartesian marks: no documented class hook

  • Polar, sunburst and geo marks document className (polar.md:42); line, area, dot, rule, text and bar marks do not.
  • Their ts-chart__* classes exist in source (line.ts:356, bar.ts:399) but are undocumented.
  • A workaround exists: ChartMark.initialize is public (types.ts:1199), and whenFocused wraps it (focus-mark.ts:33-35). No doc shows this recipe, and it cannot reach axis or focus-guide nodes.

Expected: add className to cartesian mark options (and axis / focus-guide options), matching polar. Alternative: document the wrapper recipe and which ts-chart__* names are stable. A class hook does not replace A for per-node dynamic state.

Dominant language
TypeScript
Stars
819
Forks
49
Avg merge
8h 8m
Merged PRs (30d)
11

Getting set up

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from TanStack/charts

All issues in TanStack/charts

Similar issues

More TypeScript issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.