Skip to content

feat(chart): combo charts with per-series kind and secondary value axis - #295

Merged
baseballyama merged 3 commits into
mainfrom
feat/combo-chart-secondary-axis
Aug 1, 2026
Merged

feat(chart): combo charts with per-series kind and secondary value axis#295
baseballyama merged 3 commits into
mainfrom
feat/combo-chart-secondary-axis

Conversation

@baseballyama

Copy link
Copy Markdown
Collaborator

Summary

Adds combo-chart authoring + reading + preview rendering:

  • ChartSeries.chartKind ('bar' | 'column' | 'line' | 'area') — per-series kind override, e.g. a line overlay on a column chart.
  • ChartSeries.secondaryAxis: true — plots the series against a right-hand secondary value axis (<c:valAx axPos="r"> + deleted companion <c:catAx>), the standard PowerPoint combo layout for series with mixed units (counts vs. rates/scores).

Builder

Series are split into plot groups keyed by (effective kind, axis); each group emits its own <c:barChart> / <c:lineChart> / <c:areaChart> with the right <c:axId> pair. The secondary axis pair is emitted on demand. Non-combo base kinds (pie / doughnut / scatter / radar / bubble) reject the per-series fields with a clear error.

Reader

readChartSpec now walks every plot group in the plot area (previously only the first), tags series from non-first groups with chartKind, and detects secondary-axis membership from the group's axIdvalAx[axPos="r"] mapping. Round-trip safe.

Preview

The renderer splits combo series into groups, scales each axis from its own series (valueAxis baked into filtered specs so all groups on one axis share a range), paints bars below line/area overlays, and draws secondary ticks + labels on the plot's right edge (AxisSpec.side: 'right').

Test plan

  • test/fn-chart-combo.test.ts — XML shape (both plot groups, secondary axis pair, group→axis wiring), getShapeChartSpec round-trip, pie rejection.
  • test/preview-chart-combo.test.ts — SVG assertions: bars + overlay path painted, right-edge secondary ticks at the secondary scale, single-kind path untouched.
  • Full suite: 1310 passed.

🤖 Generated with Claude Code

https://claude.ai/code/session_016az3UDqDkcNbCmWe3LoGnm

Copilot AI review requested due to automatic review settings August 1, 2026 00:42

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds “combo chart” support across the authoring pipeline (builder → OOXML), parsing (readChartSpec), and SVG preview rendering, enabling per-series chart-kind overrides and optional secondary (right-side) value axis.

Changes:

  • Extends ChartSeries with chartKind and secondaryAxis to model combo charts.
  • Updates chart builder + reader to emit/parse multiple plot groups and secondary-axis wiring.
  • Updates preview renderer + adds new tests to validate combo rendering and round-trip behavior.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
test/preview-chart-combo.test.ts Adds SVG assertions for combo rendering (bars + line overlay, right-side secondary ticks).
test/fn-chart-combo.test.ts Adds end-to-end PPTX/XML + round-trip tests for combo plot groups and secondary axis emission.
src/internal/chartml/types.ts Adds ChartSeries.chartKind and ChartSeries.secondaryAxis to the internal chart model.
src/internal/chartml/chart-reader.ts Reads multiple plot groups and tags series with chartKind / secondaryAxis during parse.
src/internal/chartml/chart-builder.ts Builds combo plot groups, introduces secondary axis pair emission, and routes groups to per-kind chart builders.
packages/preview/src/render-slide.ts Adds combo-group rendering logic and right-side value-axis rendering for secondary axis.
.changeset/combo-chart-secondary-axis.md Declares minor bumps + documents new combo chart capabilities.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +725 to +736
switch (kind) {
case 'column':
return buildBarChart(spec, sheet, 'col', seriesIndices, axes);
case 'bar':
return buildBarChart(spec, sheet, 'bar', seriesIndices, axes);
case 'line':
return buildLineChart(spec, sheet, seriesIndices, axes);
case 'area':
return buildAreaChart(spec, sheet, seriesIndices, axes);
default:
throw new Error(`combo chart: series chartKind '${kind}' is not authorable`);
}
Comment on lines 684 to +693
const series: ChartSeries[] = [];
let categoriesFromFirst: string[] | null = null;
for (const ser of allChildElements(plotted, NAME_SER)) {
const serEntries: { ser: XmlElement; groupKind: ChartKind; secondary: boolean }[] = [];
for (const group of plotGroups) {
const secondary = groupUsesSecondaryAxis(group.element);
for (const ser of allChildElements(group.element, NAME_SER)) {
serEntries.push({ ser, groupKind: group.kind, secondary });
}
}
for (const { ser, groupKind, secondary } of serEntries) {
Comment on lines +5111 to +5117
const isCombo =
isCartesian &&
spec.kind !== 'bar' &&
spec.series.some(
(s) => (s.chartKind !== undefined && s.chartKind !== spec.kind) || s.secondaryAxis === true,
);
if (isCombo) {
@baseballyama
baseballyama merged commit 6294c52 into main Aug 1, 2026
6 checks passed
@baseballyama
baseballyama deleted the feat/combo-chart-secondary-axis branch August 1, 2026 00:49
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