[Feature] `text` mark: numeric tween with a `format` function
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
- Domain
- data-visualization, frontend
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
textconverts the datum withString(datum)(text.ts:112-114); there is no numeric or format option.- The reconciler writes leaf text immediately (
motion.ts:2113-2116).
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
- No Dockerfile or Docker Compose file
- No pull request template
- Read the contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from TanStack/charts
-
[Bug] Focus guides: `url(#id)` paints ignore `idPrefix`Possibly taken A pull request linked to this issue is open or already merged. Open
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
Maintainers usually reply within 1 day
-
Renderer treats a sub-pixel width difference as a resize, which cancels the `motion()` entranceOpen
Difficulty 1/5 Under an hour Newbie friendliness 85/100
TanStack/charts#182 · 1 comment ·
Maintainers usually reply within 1 day
-
brushX with `values` can shorten the selection range when it’s dragged to the plot edgePossibly taken @andersk claimed this 7 days ago. Open
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
Maintainers usually reply within 1 day
-
Difficulty 5/5 Over a week Newbie friendliness 42/100
Maintainers usually reply within 1 day
-
Difficulty 5/5 Over a week Newbie friendliness 35/100
Maintainers usually reply within 1 day
Similar issues
-
ai-driven-qa bug claude Minor
Difficulty 2/5 1-3 hours Newbie friendliness 70/100
linagora/twake-contacts-frontend#241 ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 75/100
Maintainers usually reply within 1 day
-
ui(ListToolbar): search takes the full row on a phone instead of sharing it with the result countOpen
Difficulty 2/5 1-3 hours Newbie friendliness 64/100
Maintainers usually reply within 1 day
-
priority:high
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 70/100
ahmedkhaleel2004/gitdiagram#228 ·