Symptom
A dashboard widget authoring a genuine combo chart:
chartConfig.series = [
{ name: 'task_count', type: 'bar', yAxis: 'left' },
{ name: 'avg_progress', type: 'line', yAxis: 'right' },
]
plus two yAxis entries renders as two bar series on one shared 0–100 axis. Measured in the DOM:
| Selector |
Observed |
Expected |
.recharts-bar |
2 |
1 |
.recharts-bar-rectangle |
4 |
— |
.recharts-line-curve |
0 |
1 |
.recharts-yAxis |
1 |
2 |
So the authored per-series type and the left/right axis split are both silently dropped: a bar-and-line dual-axis chart degrades into a grouped bar chart, and avg_progress (a 0–100 percentage) is plotted against the same axis as task_count (a raw count).
Reproduced 3× on independent fresh browser launches.
Not a stale-bundle artifact — verified against objectui origin/main, which is 138 commits ahead of the vendored pin (09987b68), and it behaves identically.
Root cause
Source-confirmed, and it is two halves, both in plugin-dashboard/src/DatasetWidget.tsx:
- No
combo family. The widget resolves the chart family with CHART_TYPE_MAP[widgetType] ?? 'bar', and CHART_TYPE_MAP has no combo entry — so combo falls through to the 'bar' default. That alone explains bars-not-lines.
- The series are never forwarded.
chartConfigPresentation() in the same file deliberately does not forward series / xAxis / yAxis on the ADR-0021 dataset path, on the stated grounds that "they are DERIVED from the dataset selection". So even with a combo entry added, the authored per-series type and axis binding could never reach the renderer.
The design tension this exposes (worth a decision before someone patches half of it)
widgetDispatch.ts on origin/main routes combo as a SERIES_CHART_TYPES member, commenting that "the chart renderer has always drawn it (it derives the base family from the series)".
That is exactly the contradiction: the dispatch layer's justification for combo needing no special handling is that the renderer derives the family from series — but on the dataset path series is precisely what DatasetWidget refuses to forward. The two halves of the codebase hold opposite beliefs about who owns series on the dataset path. Fixing only half (adding a CHART_TYPE_MAP.combo entry) yields a chart that is nominally a combo but still has no line and one axis; fixing only the other half (forwarding series) collides with the "derived from dataset selection" invariant. Please settle which layer owns it, then fix both sides consistently.
Untested caveat recorded in the same run
kpi / gauge / solid-gauge / bullet all render value-only — pixel-identical to metric. No dial, no arc, no bullet target band was drawn for any of them. This was recorded as an honest caveat, not ticked as passing and not separately reproduced; it may be the same "no entry in the family map" shape or may be four distinct gaps. Worth a look while this file is open.
The other 19 chart variants pass with mark counts reconciled against API buckets, and compareTo renders its comparison series correctly.
Reproduction
- Boot the showcase (framework
a86db175, vendored console 09987b68).
- Open
/_console/apps/com.example.showcase/dashboard/showcase_chart_gallery.
- Wait for the loader to appear then clear, and let the board settle.
- Inside the "Task Count vs Avg Progress" card (widget
combo_count_vs_progress), count .recharts-bar, .recharts-bar-rectangle, .recharts-line-curve, .recharts-yAxis.
- Observe 2 / 4 / 0 / 1 against the expected 1 / — / 1 / 2. Reproduced 3×.
Re-check the two source halves:
rg -n "CHART_TYPE_MAP|chartConfigPresentation" plugin-dashboard/src/DatasetWidget.tsx
rg -n "SERIES_CHART_TYPES|combo" src/**/widgetDispatch.ts
Related
Possibly a regression of — or unfinished follow-through on — #2880 (closed completed by #2883, "ObjectChart honors the spec ChartConfig author shape"). That issue's S2 explicitly scoped dual axes as yAxis[].position + series[].yAxis: 'left'|'right', noting "combo 目前按 series 类型隐式分配,改为显式绑定优先" — the exact binding that is inert here. #2880 landed the normalisation in ObjectChart; the dataset path through DatasetWidget appears never to have been carried over, which is consistent with what this run measured.
Source
Extracted from the QA run objectstack-ai/objectstack#7515 (framework a86db175). Checklist item chart-type-matrix.
Symptom
A dashboard widget authoring a genuine combo chart:
plus two
yAxisentries renders as two bar series on one shared 0–100 axis. Measured in the DOM:.recharts-bar.recharts-bar-rectangle.recharts-line-curve.recharts-yAxisSo the authored per-series
typeand the left/right axis split are both silently dropped: a bar-and-line dual-axis chart degrades into a grouped bar chart, andavg_progress(a 0–100 percentage) is plotted against the same axis astask_count(a raw count).Reproduced 3× on independent fresh browser launches.
Not a stale-bundle artifact — verified against objectui
origin/main, which is 138 commits ahead of the vendored pin (09987b68), and it behaves identically.Root cause
Source-confirmed, and it is two halves, both in
plugin-dashboard/src/DatasetWidget.tsx:combofamily. The widget resolves the chart family withCHART_TYPE_MAP[widgetType] ?? 'bar', andCHART_TYPE_MAPhas nocomboentry — socombofalls through to the'bar'default. That alone explains bars-not-lines.chartConfigPresentation()in the same file deliberately does not forwardseries/xAxis/yAxison the ADR-0021 dataset path, on the stated grounds that "they are DERIVED from the dataset selection". So even with acomboentry added, the authored per-series type and axis binding could never reach the renderer.The design tension this exposes (worth a decision before someone patches half of it)
widgetDispatch.tsonorigin/mainroutescomboas aSERIES_CHART_TYPESmember, commenting that "the chart renderer has always drawn it (it derives the base family from the series)".That is exactly the contradiction: the dispatch layer's justification for
comboneeding no special handling is that the renderer derives the family fromseries— but on the dataset pathseriesis precisely whatDatasetWidgetrefuses to forward. The two halves of the codebase hold opposite beliefs about who ownsserieson the dataset path. Fixing only half (adding aCHART_TYPE_MAP.comboentry) yields a chart that is nominally a combo but still has no line and one axis; fixing only the other half (forwardingseries) collides with the "derived from dataset selection" invariant. Please settle which layer owns it, then fix both sides consistently.Untested caveat recorded in the same run
kpi/gauge/solid-gauge/bulletall render value-only — pixel-identical tometric. No dial, no arc, no bullet target band was drawn for any of them. This was recorded as an honest caveat, not ticked as passing and not separately reproduced; it may be the same "no entry in the family map" shape or may be four distinct gaps. Worth a look while this file is open.The other 19 chart variants pass with mark counts reconciled against API buckets, and
compareTorenders its comparison series correctly.Reproduction
a86db175, vendored console09987b68)./_console/apps/com.example.showcase/dashboard/showcase_chart_gallery.combo_count_vs_progress), count.recharts-bar,.recharts-bar-rectangle,.recharts-line-curve,.recharts-yAxis.Re-check the two source halves:
Related
Possibly a regression of — or unfinished follow-through on — #2880 (closed completed by #2883, "ObjectChart honors the spec
ChartConfigauthor shape"). That issue's S2 explicitly scoped dual axes asyAxis[].position+series[].yAxis: 'left'|'right', noting "combo 目前按 series 类型隐式分配,改为显式绑定优先" — the exact binding that is inert here. #2880 landed the normalisation inObjectChart; the dataset path throughDatasetWidgetappears never to have been carried over, which is consistent with what this run measured.Source
Extracted from the QA run objectstack-ai/objectstack#7515 (framework a86db175). Checklist item
chart-type-matrix.