Skip to content

feat(plotly): add Plotly backend with the four acceptance templates#61

Merged
Chenglong-MS merged 6 commits into
microsoft:flint-excelfrom
zl190:feat/plotly-backend
Jul 22, 2026
Merged

feat(plotly): add Plotly backend with the four acceptance templates#61
Chenglong-MS merged 6 commits into
microsoft:flint-excelfrom
zl190:feat/plotly-backend

Conversation

@zl190

@zl190 zl190 commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

What

Refs #54 (scope claimed there). Adds assemblePlotly as a fourth backend with the four acceptance templates from docs/adding-a-backend.md §6: Bar Chart, Line Chart, Area Chart, Scatter Plot. Further templates as follow-ups, per the guide's parity note.

Implementation

  • The orchestrator reuses the shared pipeline (semantic resolution, zero decisions, temporal conversion, layout) and only Phase 2 is new: it emits a { data, layout } figure that is plain JSON — no callback functions anywhere, asserted by a recursive check and a JSON.parse(JSON.stringify(fig)) round-trip test.
  • Each template mirrors the chartjs template's decisions for the same chart (category handling, color grouping, zero baseline from the semantic decision, ordinal sort order).
  • column / row facets compile to Plotly subplot grids, following the chartjs facet decisions: shared nice y-domain, y ticks and title on the leftmost column only, column-only wrapping by facet budget, column headers as annotations. Row headers sit on the right (the left edge is taken by y labels in a composed figure — noted in code comments).
  • Colors go through a colormap.ts that consumes the core color-decisions layer (explicit scheme → schemeType/cardinality-based pick → Plotly qualitative default), mirroring the chartjs colormap's strategy with Plotly-native palettes.
  • §4 wiring: barrel export, tsup entry, ./plotly subpath, smoke test, plotly.js as an optional peerDependency matching the other renderers, and two dedicated test-data generators (Plotly: Core Templates, Plotly: Facets) registered in TEST_GENERATORS.
  • §5 site: PlotlyView component + supported-backends.ts entry, so the templates render on the standard gallery matrices.

One known simplification: with a diverging scheme (e.g. Temperature), a single-trace bar picks one ramp color rather than mapping values through the colorscale; continuous value→color mapping is a larger change and is left as a follow-up.

Verification

  • tests/plotly-backend.test.ts — 15 cases + a smoke-test addition (registry guard, per-template shape, zero baseline, color grouping, facet grids: column / row / 2×2 / legend dedup, diverging vs categorical scheme pick, generator round-trip, JSON purity incl. facet figures)
  • Full suite: 439 + 50 passing; typecheck clean across flint-js, flint-mcp, and site; npm run build produces dist/plotly (ESM/CJS/DTS); eslint clean on new files
  • Lockfile: adds the plotly.js-dist-min site dependency

Rendered on the same inputs across all four backends (Vega-Lite, ECharts, and Chart.js as the parity reference), plus the facet grids:

Flint: one input compiled through all four backends and rendered side by side; the new Plotly backend is gold-framed

Plotly column and row facet grids

🤖 Generated with Claude Code

zl190 and others added 5 commits July 18, 2026 23:04
Add a fourth rendering backend per docs/adding-a-backend.md: an
assemblePlotly orchestrator reusing the shared core pipeline
(Phase 0 semantics / Phase 1 layout), diverging only at Phase 2 to
emit Plotly figures ({ data: traces[], layout }). Figures are pure
JSON — temporal axes use Plotly's native date axis instead of tick
callbacks, so compiled specs survive serialization.

First-merge scope (§6 acceptance): Bar, Line, Area, Scatter templates
mirroring the Chart.js templates' decisions (category order, zero
baseline, color grouping, horizontal bar transposition, interpolate /
opacity / stackMode / showPoints properties). column/row facet
encodings are dropped with an 'unsupported-channel' warning; subplot
grids are a follow-up.

Wiring per §4: barrel export, tsup entry, ./plotly subpath export,
plotly.js as an optional peerDependency (mirrors chart.js), smoke
test, and tests/plotly-backend.test.ts (10 cases incl. a recursive
no-functions JSON-purity check).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
PlotlyView (plotly.js-dist-min, designed-size wrapper mirroring
ChartjsView), a BACKENDS adapter entry, and the per-view dispatch
lines in WallChart / TripleChart / DocChart. Editor output language
and ChartWall result names gain their 'plotly' entries.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Facets: column/row encodings render as a subplot grid (facet.ts) —
per-panel axis pairs with explicit domains, mirroring the Chart.js
backend's facet decisions: shared nice-rounded y-domain, y tick
labels and title on the leftmost column only, column-only wrapping
from the shared facet budget, column headers above panels. Row
headers sit on the right (Vega-Lite style) because the left edge is
occupied by y labels in a single combined figure; x-axis titles show
on the bottom row only for the same reason. The first-merge
'unsupported-channel' warning path is gone — all four templates now
declare column/row.

Colors: colormap.ts mirrors chartjs/colormap.ts — core color
decisions (schemeType / schemeId / categoryCount) pick from
Plotly-native palettes (plotly10 / light24 qualitative, viridis
sequential, RdBu diverging); templates thread the resolved palette
instead of indexing the default colorway directly.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
genPlotlyCoreTests (four templates, color on/off, horizontal bar) and
genPlotlyFacetTests (column / row / column-row grid), registered as
'Plotly: Core Templates' and 'Plotly: Facets' in TEST_GENERATORS per
the adding-a-chart-template §4 generator pattern. The backend test
file grows facet-grid assertions (axis pairs, shared range,
leftmost-only labels, header annotations, legend dedupe), a
diverging-vs-categorical scheme pick, a generator round-trip that
assembles every dedicated case, and keeps the JSON-purity check over
a facet figure.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Regenerate package-lock.json from origin/dev and re-add just the
plotly entries (plotly.js-dist-min package + site dependency,
plotly.js peerDependency + peerDependenciesMeta), dropping the
unrelated peer-flag churn a full npm install had introduced.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@Chenglong-MS

Copy link
Copy Markdown
Contributor

This is a fantastic work stream. Let me take a look.

zl190 added a commit to zl190/flint-chart that referenced this pull request Jul 19, 2026
@Chenglong-MS
Chenglong-MS changed the base branch from dev to flint-excel July 22, 2026 05:54
@Chenglong-MS

Copy link
Copy Markdown
Contributor

@copilot resolve the merge conflicts in this pull request

@Chenglong-MS
Chenglong-MS merged commit 58a75c1 into microsoft:flint-excel Jul 22, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants