Repository navigation
Conversation
Outside pie labels built from radialRule and radialText sit on their slice angle, so labels of small adjacent slices overlap. radialLabels stacks labels on each side, moves overlapping labels apart as little as possible, and hides the lowest-priority labels when they do not fit. maxShift optionally hides labels that would move too far from their slice.
Measure label text with the chart's text measurer and hide labels that would cross the left or right edge, so narrow charts and long labels stay inside the surface. Equal priorities now hide the later label first. Tests cover narrow and resized charts, long labels, maxShift removal, and stable keys.
radialLabels emits only polyline and label scene nodes. These tests confirm each renderer paints every visible connector and label.
Keyed labels and connectors keep their elements and interpolate to the new layout, and labels of removed slices fade out before removal.
🦋 Changeset detectedLatest commit: 3797bfb The changes in this PR will be included in the next version bump. This PR includes changesets to release 12 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
|
Important Draft PR not reviewedDraft PRs are not automatically reviewed by default.
To automatically review draft PRs, update your CodeRabbit configuration: reviews:
auto_review:
drafts: true
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
Thanks @hshoja, the requested cases are useful. I independently checked the layout helper at One performance improvement before this is ready: the capacity loop calls A private prototype selected the highest-priority I have not settled the separate-mark API choice yet, and the reported bundle costs and full validation still need independent verification. |
|
One more case from a rendered check of My fixture uses 20 rows in input order, All three engines kept labels inside the chart, with no label-to-label overlaps, at 640 × 320, 220 × 320 and 640 × 100. Visible label counts matched interaction-point counts. The connector routes still need a clear corridor beside the text when labels are spread vertically. I also measured the existing 114 consumer entries independently: 108 are byte-identical, six polar entries change by +0.026 kB minified, at most +0.009 kB gzip and +0.068 kB Brotli. No budget changes are approved by this review. |
Removing the lowest-priority label one at a time rescanned and copied the side for every removal, which is quadratic when many labels cannot fit. Sort once by priority, keep the labels that fit, and filter the angular order through that selection. The maxShift loop is unchanged.
Labels followed a curve, so a slanted connector to an outer label could pass through a neighbor's text when labels were spread vertically. Each side now places its text in one column outside the outermost visible elbow, so every connector stays on the inner side of all text. When the column does not fit, the lower-priority one of the outermost-elbow label and the widest label is hidden, preferring the outermost-elbow label on ties because it sets the column.
|
Thanks for both reviews. Both points are fixed. 1. Faster selection when labels do not fit (8c41042)Before, the code removed the weakest label one at a time and scanned the whole list each time. Now it sorts by priority once, keeps the top labels that fit, and keeps them in slice order. Ties still keep the earlier row, and the Example: 5,000 labels on one side with room for 25 took 152.5 ms, and now take about 1 ms. New tests check that the result is the same as the old one-at-a-time removal (50 inputs), that slice order is kept, and the 5,000-label case. 2. Connectors no longer cross other labels (7d57e93)Before, labels followed a curve, so a slanted connector could pass through a neighbor's text. Now all labels on one side start at the same x, just outside the outermost connector. Every connector ends before the text starts, so it cannot cross another label. If the text does not fit the chart width, the mark hides either the label with the outermost connector or the widest label, whichever has the lower priority. On a tie it hides the outermost one, because that label pushes the column out. Your fixture, with text boxes grown by 2 px (red = connector crosses a label):
Your fixture is now a test. It checks every connector against every other label at all three sizes. On the old code it fails with Ideas for laterNot in this PR, until the API is decided:
|
The API shape is not settled, so expose only options that change behavior: priority, maxShift, and the text and style options. Connector offset, elbow length, text padding, and line height become internal defaults; line height follows fontSize.
numericField duplicated the existing numberProperty helper that radialArc uses for its datum defaults. Document the mark with the option table used by the other polar marks, and shorten the friction entry to the format of recent entries.
|
Thanks @hshoja, I rechecked the rendered fixture at Firefox reports a slightly wider SVG text bounding box than the text advance. I compared screenshots with SVG overflow visible versus clipped, and there were zero changed pixels in all three engines for these fixtures. I do not see painted clipping here. The revised layout helper also passed 1,812 bounds, spacing and connector-column cases per engine, plus the 5,000-label case with capacity 25. That helper was checked at At the current head, 108 of the 114 existing consumer bundles remain byte-identical. The six changed polar bundles add 0.026 kB minified, at most 0.009 kB gzip and 0.073 kB Brotli. These measurements compare the reviewed source overlay against the current checkout, not a newly approved budget baseline. The two specific review concerns, repeated capacity scans and connector crossings in this fixture, are addressed. The separate-mark API choice, bundle acceptance and full CI remain open, so this is not merge approval. |


Refs #227 - outside labels of small adjacent pie slices overlap, and there is no built-in way to spread or hide them.
radialLabelsmark in@tanstack/charts/polar: outside labels with elbow connectors, one text column per sidepriority(default: datumvalue);maxShiftalso hides labels that move too farScreenshot:

How to review: start at
polar-label-layout-internal.ts(pure layout), thenradialLabelsinpolar.ts; the rest is tests and docsHow to test:
pnpm vitest run packages/charts-core/src/polar-label-layout-internal.test.ts packages/charts-core/src/polar-radial-labels.test.tsMore screenshots
maxShift: 24hides labels that would move too far from their slice:Review fixture, before and after the text column (red = connector crosses a label):
Requested cases
maxShiftkey; connector keys add:connectormotion(), labels and connectors move to the new layout; hidden labels fade outlabelandpolylinenodes; tested in SVG, Canvas, and React NativeradialLabels; about 2.3 kB gzip when importedSeparate mark or
radialTextoptionradialTextoption: fewer exports, butradialTextwould need connector options, and hiding a label breaks its rule that every valid row renders.Local checks
Type check, docs check, and new and changed tests pass.
bundle:checkfails the same way on cleanmain;package:checkfails on a local Node version mismatch (24.7.0 vs.nvmrc24.18.0).