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

[Feature] `text` mark: numeric tween with a `format` function

Open
#215 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
57/100
Issue type
Feature
Clarity
Mostly clear
Activity status
Active
Tech stack
d3, typescript

Research direction

Read packages/charts-core/src/text.ts around lines 112–114 and packages/charts-core/src/motion.ts around lines 2113–2116, then run the provided Vitest repro. Trace how text marks are rendered and how the reconciler handles text leaves; define completion by intermediate formatted values appearing during the tween, the final text matching the target exactly, and reduced motion retaining the snap behavior.

Written by the indexing model from the issue text.

Description

Version: @tanstack/charts 1.1.0 (57774e1). Split from #193 (section B) so it can be closed on its own.

A text mark showing a number (a total in a donut centre, a value label) jumps to the new string while the marks around it animate.

Why
Repro

Save as packages/charts-core/src/repro.test.ts, run pnpm vitest run packages/charts-core/src/repro.test.ts (vitest + jsdom, rAF driven by hand).

import { expect, it, vi } from 'vitest'
import { scaleLinear } from 'd3-scale'
import { defineChart, text } from './index'
import { motion } from './motion'
import { createChartScene } from './scene'

it('numeric text content tweens', () => {
  const queue: FrameRequestCallback[] = []
  const tick = (t: number) => queue.splice(0).forEach((f) => f(t))
  vi.spyOn(window, 'requestAnimationFrame').mockImplementation((f) => queue.push(f))
  vi.spyOn(window, 'cancelAnimationFrame').mockImplementation(() => {})
  const el = document.createElement('div')
  const s = motion({ transition: { type: 'tween', duration: 1000, easing: 'linear' } }).mount(el, () => {})
  const scales = { x: { scale: scaleLinear }, y: { scale: scaleLinear } }
  const render = (v: number) => s.render(createChartScene(defineChart({ scales, guides: false,
    marks: [text([v], { x: () => 0.5, y: () => 0.5, text: (d) => d.toFixed(0) })] }), { width: 300, height: 200 }), { ariaLabel: 'x' })
  render(10); tick(0); tick(2000)
  render(90); tick(0)
  const seen = new Set<string>()
  for (const t of [250, 500, 750]) { tick(t); seen.add(el.querySelector('text')!.textContent!) }
  expect([...seen].length).toBeGreaterThan(1)
})

Output on 57774e1: distinct textContent values at 250/500/750 ms = [ '90' ] (expected more than 1).

Ask

An opt-in numeric text tween that writes the formatted string each frame and ends on the exact target; reduced motion keeps the snap. For example a format?: (value: number) => string option on text plus a motion opt-in.

Related: #193.

Dominant language
TypeScript
Stars
819
Forks
49
Avg merge
12h 9m
Merged PRs (30d)
6

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.