fix(vegalite): Waterfall axis titles: display names, no __wf_lead - #79
Merged
Conversation
The Waterfall template rebuilds its own encoding objects, and it read only `.field` off `ctx.resolvedEncodings` — discarding the titles the assembler had already resolved from `field_display_names`. The bar layer hardcoded the raw field name, and the shared x encoding carried no title at all. Vega-Lite derives an axis title from the field name of every untitled encoding on a shared scale and concatenates them, so the untitled x also picked up the internal connector column: the axis rendered as "week, __wf_lead". Carrying the resolved titles across fixes both symptoms at once. An explicit title on the primary channel settles the whole shared scale, so the internal columns need no treatment of their own — `title: null` on them would blank the axis instead, since an explicit null anywhere in a shared-scale title set wins. Verified by compiling with vl.compile and reading the Vega axis titles, not just the assembled spec. Swept every bundled gallery case: Waterfall was the only template leaking an internal column into an axis title. 652 tests passing. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Chenglong-MS
approved these changes
Jul 31, 2026
Chenglong-MS
added a commit
that referenced
this pull request
Aug 2, 2026
Brings the waterfall resolved-axis-title fix (#79). Both branches had independently fixed the same bug — the internal `__wf_lead` / `__wf_connector_y` helper columns leaking into the merged waterfall axis title. dev's fix supersedes this branch's: - this branch pinned the x title to the raw `xField`; - dev pins the *resolved* `xTitle`, which falls back to `xField` but honours a caller-supplied label. Resolved in favour of dev, keeping this branch's explanatory comment. Also carried the same reasoning to the three helper layers this branch still nulled (`__wf_connector_y`, `__wf_sum`, `__wf_center`): a `title: null` on a primary channel resolves the merged title to nothing and blanks the axis for every layer on the shared scale, which is the invariant dev's new waterfall-titles suite asserts. They now carry `yTitle`, matching the bar layer. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 175e0e03-5dda-4a02-aa14-c181660b9c99
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
field_display_nameswas ignored on both axes, and the internal window-transform column surfaced in the rendered x-axis title asweek, __wf_lead.instantiate()rebuilds its own encoding objects and drops the titles the assembler had already resolved, leaving the shared x scale untitled, so Vega-Lite derived a title from every untitled field on that scale and concatenated them.Context
Fixes #65, fixes #66.
#66 looks like an accidental re-post of #65: same text nine minutes apart, only the sample field name differs. Referencing both so neither is left dangling; happy to drop one if you would rather keep them separate.
Both were filed against 0.3.0. The defect still reproduces on
dev@c73d597:week, __wf_leadwsu_changeWeek (Mon, JST)WSU weekly changeChanges
packages/flint-js/src/vegalite/templates/waterfall.ts(+16 / −1):xTitle/yTitlefromctx.resolvedEncodings, whichbuildVLEncodingshas already populated with anyfield_display_namesoverride (vegalite/assemble.ts:1021).xEncan explicittitle. This is what stops the concatenation: an explicit title on the primary channel settles the title for the whole shared scale.yTitleon the bar layer instead of the hardcoded rawyField.packages/flint-js/tests/waterfall-titles.test.ts(new, 4 cases).Review focus
title: nullon the internal bindings, blanks the axis instead: Vega-Lite merges titles across every layer on a shared scale and an explicitnullanywhere in that set wins. Compiling that variant blanks the axis (see Test plan); if you would rather suppress differently, say so and I will redo it.titlewhere it previously had none — tell me if that matters for any downstream consumer.Test plan
npx vitest run tests/waterfall-titles.test.ts— 4 pass. Reverting the template change makes 3 of them fail; the 4th is a forward guard that passes either way by design.npm run test:js— 652 pass across 39 files, up from 648 across 38 ondev@c73d597. The delta is this PR's new file; no existing test needed changing.vl.compileand read the axis titles out of the resulting Vega spec. Before: xweek, __wf_lead, ywsu_change. After: xWeek (Mon, JST), yWSU weekly change.packages/flint-js/src/test-data(931 instances, of which 880 assemble on the Vega-Lite backend; the other 51 are backend-specific cases that do not). Ondev@c73d597: 10 hits, all Waterfall. With this change: 0.dev@c73d597and on this branch and diffed: no display names; display names; missing x; missing y; no encodings at all (the|| 'Category'/|| 'Amount'fallbacks); an explicit Type column;totals: 'both'withshowTextLabels: true, which binds two more internal columns to the y scale; an escaped field name; column facet; row facet. All ten leak__wf_leadondevand all ten are clean after. Nothing throws, and the fallback titles still readCategory/Amount. Escaped names improve as a side effect: the x title wasa\.b, __wf_leadand is nowa.b.title: nullalternative from the issue, to check the claim in Review focus 1: with nulls on the internal bindings the compiled Vega spec carries no x-axis title at all.npx eslint src/vegalite/templates/waterfall.ts— clean.The tests assert on the assembled Vega-Lite spec rather than compiling, because
vega-liteis only an optional peer dependency offlint-jsand resolves here by hoisting; I did not want to add a test-time import that is not a declared dependency. The compile-level check above was run separately.Notes for reviewers
Scope. In that 880-instance sweep, Waterfall is the only template that leaks an internal column into an axis title, so this is a template-local fix rather than an assembler-level guard.
Adjacent defect, not fixed here. The same sweep shows Violin, ECDF and Density also drop
field_display_nameson one axis, via a different mechanism: a pivoted synthetic column, or a template setting its own title, which preempts the!encodingObj.titleguard inbuildVLEncodings. Happy to open a separate issue.Cross-language parity — worth a look, and it predates this branch.
packages/flint-pymirrors this template, andflint/vegalite/templates/waterfall.pyhas the display-name half of the same defect:x_enc(lines 59-64) carries no title, line 90 hardcodes"title": y_field.I left Python alone. While checking whether to mirror the fix, I found the Python template is behind the TypeScript one by more than titles: it emits a single
barlayer with no connector rule and no__wf_leadat all. The 8 Waterfall fixtures undershared/test-data/record that same older shape — 1 layer, no__wf_lead— so the stored "JS reference" already does not match whatflint-jsondevemits today (2 layers,bar+rule). Those 8 tests pass because Python and the fixtures are stale in the same direction, not because the two implementations agree. For context,uv run pytestinpackages/flint-pyis 180 failed / 600 passed ondev@c73d597, before this branch.So mirroring the title fix into Python on its own would not land cleanly: I tried it, and all 8 Waterfall fixtures go red, because Python would then emit the corrected titles while the stored reference still holds the old ones. Getting Python genuinely back in step looks like a larger job than this PR — the connector layer, then the titles, then a fixture regeneration — and it depends on a regeneration tool I could not find in the repo. Happy to take it on as a follow-up if you want it, and happy to file it as an issue instead. Flagging rather than guessing.
CI will be red on typecheck, from before this branch.
dev@c73d597does not typecheck on its own:src/vegalite/templates/scatter.ts(338,28): error TS7006. Verified against a clean checkout with this branch's changes removed. Also worth knowing:tsc --noEmitaborts there before reachingtsconfig.test.json, sonpm run typechecknever gets as far as typechecking the tests. I ran the test config separately and it is clean.