Skip to content

Waterfall Chart ignores field_display_names and leaks internal __wf_lead field into axis title #66

Description

@soh-tetsu

Summary

On Waterfall charts, field_display_names is ignored and the internal window-transform field __wf_lead leaks into the x-axis title. Line/Bar/Area charts apply field_display_names correctly, so this is Waterfall-template–specific.

Verified against flint-chart@0.3.0 (via flint-chart-mcp@0.3.0). Source refs at main (commit 95b2552).

Repro

compile_chart, backend vegalite:

{
  "chart_spec": {
    "chartType": "Waterfall Chart",
    "encodings": { "x": { "field": "week" }, "y": { "field": "dau_change" } }
  },
  "field_display_names": { "dau_change": "DAU weekly change", "week": "Week (Mon, JST)" }
}

Observed: compiled spec has "title": "dau_change" on the y encoding; the x-axis title renders as week, __wf_lead. Neither display name is applied.

Expected: y-axis title "DAU weekly change", x-axis title "Week (Mon, JST)", no internal field in any title.

The same input on Line / Bar / Area charts applies both display names correctly — so the generic assembler path is fine; only the Waterfall template is affected.

Root cause

packages/flint-js/src/vegalite/templates/waterfall.ts, instantiate():

  1. buildVLEncodings (in vegalite/assemble.ts) already writes the display name onto resolvedEncodings.{x,y}.title. The template destructures ctx.resolvedEncodings but discards those titles, hardcoding the raw field name:

    const { x, y, color, column, row } = ctx.resolvedEncodings;
    // ...
    y: {
        field: "__wf_prev_sum",
        type: "quantitative",
        title: yField,          // ← raw field, ignores y.title (the display name)
        ...
    },
  2. The shared xEnc sets no title, so VL auto-derives it from the field. The connector-rule layer adds x2: { field: "__wf_lead" } (also untitled), and VL concatenates every untitled field on the shared x scale into one axis title → "week, __wf_lead".

Suggested fix

Use the titles the assembler already resolved, and suppress internal fields:

const xTitle = x?.title ?? xField;
const yTitle = y?.title ?? yField;

const xEnc = {
    field: xField,
    type: "ordinal" as const,
    sort: null,
    axis: { labelAngle: -45 },
    title: xTitle,                      // was absent
};

// bar layer:
y: { field: "__wf_prev_sum", type: "quantitative", title: yTitle, /* ... */ },

// connector layer — internal fields must never title the shared axis:
x:  { field: xField,      type: "ordinal", sort: null, bandPosition: 0, title: null },
x2: { field: "__wf_lead", bandPosition: 1, title: null },

General guard: any layer encoding bound to a __wf_* / internal field should set title: null (or axis: { title: null }) so VL never surfaces it.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions