microsoft / microsoft/flint-chart
ECharts: legend.left is baked to the design canvas, so chart.resize() overlaps the plot
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 4.2k
- Forks
- 235
- Avg merge
- 17h 45m
- Merged PRs (30d)
- 11
Description
Summary
assembleECharts places the categorical legend (and the matching legend-title graphic) at an absolute left in design-canvas pixels. That is correct when the host inits ECharts at _width × _height. It breaks as soon as a host puts the chart in a fluid container and calls the official chart.resize().
This is not an ECharts resize() bug. resize() only changes the canvas / grid / axes; it does not rewrite option pixel fields. Flint is the one emitting legend.left relative to _width.
Verified against flint-chart@0.4.1. The same left: legendLeftPx path is still in main (packages/flint-js/src/echarts/instantiate-spec.ts, legend-positioning block). I did not find an existing issue for this.
Repro
Slope Chart (any multi-series cartesian chart with a right-side categorical legend works):
import { assembleECharts } from 'flint-chart/echarts';
import * as echarts from 'echarts';
const option = assembleECharts({
data: { values: [
{ period: '2024', team: 'Alpha', nps: 32 },
{ period: '2025', team: 'Alpha', nps: 48 },
{ period: '2024', team: 'Beta', nps: 41 },
{ period: '2025', team: 'Beta', nps: 39 },
{ period: '2024', team: 'Gamma', nps: 28 },
{ period: '2025', team: 'Gamma', nps: 52 },
{ period: '2024', team: 'Delta', nps: 55 },
{ period: '2025', team: 'Delta', nps: 61 },
]},
semantic_types: { period: 'Year', team: 'Name', nps: 'Score' },
chart_spec: {
chartType: 'Slope Chart',
encodings: {
x: { field: 'period' },
y: { field: 'nps' },
color: { field: 'team' },
},
baseSize: { width: 420, height: 280 },
},
});
// Typical host: fill the reading column, then resize.
const el = document.getElementById('chart');
el.style.width = '100%'; // e.g. 800px
el.style.height = option._height + 'px';
const chart = echarts.init(el);
chart.setOption(option);
chart.resize();
Assembled bookkeeping on 0.4.1:
| field | value |
|---|---|
_width / _height |
534 × 377 |
grid.right |
112 (plot ends at canvasW − 112) |
legend.left |
422 |
legend-title graphic.left |
422 |
422 + 112 = 534. The legend’s left edge is meant to sit on the plot’s right edge only when the canvas is 534px wide.
Actual
- Canvas 534px (Flint’s contract): legend sits in the reserved gutter. Correct.
- Canvas 800px +
resize(): plot stretches to800 − 112 = 688, legend stays atleft: 422→ overlaps the series. - Canvas 350px +
resize():legend.left: 422is past the right edge → clipped / gone.
grid.left / grid.right as pixel insets still work at any width. Only left-origin design coordinates (legend.left, title graphic.left, and similarly series.radius: 'NNpx' on sunburst/pie) do not.
Expected
One of:
- Document the contract in the ECharts assemble docs: hosts must init/size the DOM to
_width × _height(or CSS-scale that box). Fluidwidth: 100%+resize()is unsupported. - Emit fluid-safe positions so official
resize()keeps the legend in the gutter:legend.right(and the title graphic) instead oflegend.left: designW − gutter, orleft: 'right'/ percent, withgrid.rightstill reserving the same gutter.
Option 2 is a small change in ecApplyLayoutToSpec and would let note/editor hosts follow the ECharts handbook (width: 100% + resize()) without rewriting Flint’s option.
A host-side conversion of left → right = _width - left is wrong: ECharts right is the inset to the component’s right edge, so the legend grows left into the plot even at design size.
Why this shows up in hosts
Flint’s own MCP / gallery path paints at a fixed canvas (create_chart_view is described as fixed-size). Editors that share a reading column with prose (and iPhone/iPad widths) cannot dedicate _width forever, and resize() is the documented ECharts way to follow the container.
Related but separate: sunburst/pie radius: [\${n}px`, ...]` is also design-canvas-absolute and clips when the live box is smaller. Happy to split that if you want a narrower first fix.
Environment
flint-chart@0.4.1(reproduced)mainas of 2026-08-15 still useslegendLeftPx = effectiveChartWidth - rightMarginPx- Apache ECharts 5 / 6 (behavior of
legend.leftvsresize()is the same)
Contributor 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.
Research direction
Start in packages/flint-js/src/echarts/instantiate-spec.ts, especially the legend-positioning block and ecApplyLayoutToSpec. Reproduce the supplied assembleECharts example at the design width and at wider and narrower container widths, then verify that the chosen positioning behavior keeps the legend and title graphic out of the plot after chart.resize().
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- data-visualization
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 55/100