From 43446bb805a4b388caea43480344162596aea7a3 Mon Sep 17 00:00:00 2001 From: Tanner Linsley Date: Wed, 26 Aug 2026 11:02:05 -0600 Subject: [PATCH] Add multiple-axis examples --- .../conformance/DEFINITION-COVERAGE-AUDIT.md | 2 +- .../DEFINITION-COVERAGE-OVERVIEW.md | 2 +- .../cases/70-composed-chart/case.json | 11 +-- .../cases/70-composed-chart/example.tsx | 34 ++++++++- .../cases/70-composed-chart/recharts.ts | 40 ++++++++++- .../cases/70-composed-chart/tanstack.test.ts | 29 +++++++- .../cases/70-composed-chart/tanstack.ts | 6 +- benchmarks/conformance/catalog-index.json | 11 +-- .../previews/70-composed-chart.svg | 2 +- benchmarks/conformance/previews/manifest.json | 6 +- docs/config.json | 2 +- docs/reference/scales-guides-and-color.md | 2 + examples/sandbox/src/App.tsx | 35 ++++++++++ examples/sandbox/src/plots.ts | 69 +++++++++++++++++++ examples/sandbox/src/styles.css | 4 ++ packages/charts-core/docs/config.json | 2 +- .../docs/reference/scales-guides-and-color.md | 2 + scripts/catalog-preview.mjs | 3 + scripts/catalog-preview.test.mjs | 3 + 19 files changed, 239 insertions(+), 26 deletions(-) diff --git a/benchmarks/conformance/DEFINITION-COVERAGE-AUDIT.md b/benchmarks/conformance/DEFINITION-COVERAGE-AUDIT.md index 66bca66c..0dd3a650 100644 --- a/benchmarks/conformance/DEFINITION-COVERAGE-AUDIT.md +++ b/benchmarks/conformance/DEFINITION-COVERAGE-AUDIT.md @@ -142,7 +142,7 @@ ownership boundary. | [54 — Bump ranking](./cases/54-bump-ranking/example.tsx) | Definition now | Public ranking and maximum-date selection feed native line, dot, and text marks. | | [59 — Grouped reducer bars](./cases/59-grouped-reducer-bars/example.tsx) | Definition now | Public grouped mean output feeds native bars and labels. | | [60 — Lag autocorrelation](./cases/60-lag-autocorrelation/example.tsx) | Definition now | Public two-row windows form lag pairs for native dots and a reference line. | -| [70 — Composed chart](./cases/70-composed-chart/example.tsx) | First-party primitive | Native `barY.maxThickness` applies a centered cap after final band, subgroup, and inset resolution; one private resolver also serves `barX`. | +| [70 — Three-axis composed chart](./cases/70-composed-chart/example.tsx) | First-party primitive | Named scales place precipitation and wind on stacked right axes, while native `barY.maxThickness` caps the final resolved band. | | [72 — Mixed bars](./cases/72-recharts-mixed-bars/example.tsx) | Definition now | Public grouped bar layout expresses adjacent stacked and independent slots. | | [73 — Many-point scatter](./cases/73-many-point-scatter/example.tsx) | Definition now | Native dots own explicit keys and a configured radius scale over selected source rows. | | [102 — World choropleth](./cases/102-world-choropleth/example.tsx) | Definition now | `geoShape`, a public Equal Earth descriptor, and threshold color render joined countries. | diff --git a/benchmarks/conformance/DEFINITION-COVERAGE-OVERVIEW.md b/benchmarks/conformance/DEFINITION-COVERAGE-OVERVIEW.md index 48840901..c2a456c1 100644 --- a/benchmarks/conformance/DEFINITION-COVERAGE-OVERVIEW.md +++ b/benchmarks/conformance/DEFINITION-COVERAGE-OVERVIEW.md @@ -132,7 +132,7 @@ presentation policy. | [63-violin-distributions — Violin distribution comparison](./cases/63-violin-distributions/example.tsx) | First-party primitive | `violin-mark` | `example.tsx`, `tanstack.test.ts` | | [64-marimekko-mosaic — Marimekko survey composition](./cases/64-marimekko-mosaic/example.tsx) | First-party primitive | `mosaic-layout` | `example.tsx`, `tanstack.test.ts` | | [65-voronoi-nearest-tooltip — Voronoi nearest-point interaction](./cases/65-voronoi-nearest-tooltip/example.tsx) | Optional primitive | `spatial-voronoi` | `example.tsx` | -| [70-composed-chart — Layered Seattle weather chart](./cases/70-composed-chart/example.tsx) | First-party primitive | `bar-max-thickness` | `example.tsx`, `tanstack.test.ts` | +| [70-composed-chart — Seattle weather with three y axes](./cases/70-composed-chart/example.tsx) | First-party primitive | `bar-max-thickness` | `example.tsx`, `tanstack.test.ts` | | [71-recharts-population-pyramid — Palmer penguins by species and sex](./cases/71-recharts-population-pyramid/example.tsx) | Definition now | `current-definition-api` | `example.tsx`, `tanstack.test.ts` | | [72-recharts-mixed-bars — Stacked and adjacent Seattle weather bars](./cases/72-recharts-mixed-bars/example.tsx) | Definition now | `current-definition-api` | `example.tsx` | | [73-many-point-scatter — Automobile specifications scatter](./cases/73-many-point-scatter/example.tsx) | Definition now | `current-definition-api` | `example.tsx`, `tanstack.test.ts` | diff --git a/benchmarks/conformance/cases/70-composed-chart/case.json b/benchmarks/conformance/cases/70-composed-chart/case.json index eb6a559a..62dac152 100644 --- a/benchmarks/conformance/cases/70-composed-chart/case.json +++ b/benchmarks/conformance/cases/70-composed-chart/case.json @@ -3,15 +3,16 @@ "referenceRenderer": "recharts", "order": 700, "id": "70-composed-chart", - "title": "Layered Seattle weather chart", + "title": "Seattle weather with three y axes", "family": "composition", - "intent": "Compare daily maximum temperature, precipitation, minimum temperature, and wind using an area, bars, a line, and points.", + "intent": "Compare daily temperature, precipitation, and wind without forcing unlike units onto one y scale.", "support": "composed", "features": [ "mixed marks", + "independent y scales", + "left axis and stacked right axes", "daily observations", "monotone curves", - "shared numeric scale", "resolved maximum bar thickness" ], "geometry": [ @@ -25,7 +26,7 @@ "url": "https://recharts.github.io/en-US/examples/LineBarAreaComposedChart/" }, "ai": { - "create": "Create one chart from Seattle weather observations that layers maximum temperature as an area, precipitation as bars, minimum temperature as a monotone line, and wind as red points.", - "maintain": "Select a different weather window while preserving source dates and measures, mark order, colors, and cast-free channel inference." + "create": "Create one chart from Seattle weather observations that uses a left temperature axis, an independent right precipitation axis for bars, and a second right wind axis for points.", + "maintain": "Select a different weather window while preserving source dates, units, named scale bindings, stacked right axes, mark order, colors, and cast-free channel inference." } } diff --git a/benchmarks/conformance/cases/70-composed-chart/example.tsx b/benchmarks/conformance/cases/70-composed-chart/example.tsx index ff24f8fe..02187acb 100644 --- a/benchmarks/conformance/cases/70-composed-chart/example.tsx +++ b/benchmarks/conformance/cases/70-composed-chart/example.tsx @@ -32,6 +32,7 @@ export const createExampleChart = (input: ChartOptions) => { id: 'precipitation-bars', x: 'date', y: 'precipitation', + yScale: 'precipitation', fill: '#413ea0', maxThickness: 20, }), @@ -43,8 +44,10 @@ export const createExampleChart = (input: ChartOptions) => { curve: monotone, }), dot(rows, { + id: 'wind-points', x: 'date', y: 'wind', + yScale: 'wind', fill: '#ef4444', r: 4.5, }), @@ -56,10 +59,35 @@ export const createExampleChart = (input: ChartOptions) => { ticks: { format: (value: Date) => dateFormat.format(value) }, }, }, - y: { scale: scaleLinear, grid: true, axis: { ticks: { count: 5 } } }, + y: { + scale: scaleLinear, + grid: true, + axis: { + label: 'Temperature (°C)', + ticks: { count: 5 }, + }, + }, + precipitation: { + channel: 'y', + side: 'right', + scale: scaleLinear, + axis: { + label: 'Precipitation (mm)', + ticks: { count: 5 }, + }, + }, + wind: { + channel: 'y', + side: 'right', + scale: scaleLinear, + axis: { + label: 'Wind (m/s)', + ticks: { count: 5 }, + }, + }, }, - margin: { top: 20, right: 20, bottom: 50, left: 80 }, + margin: { top: 20, bottom: 50 }, }, { keyboard: true, tooltip: exampleTooltip }, ) @@ -68,7 +96,7 @@ export interface ChartOptions { revision: number } -export const exampleAriaLabel = 'Layered Seattle weather' +export const exampleAriaLabel = 'Seattle weather with three y axes' export const chart = createExampleChart({ revision: 0, diff --git a/benchmarks/conformance/cases/70-composed-chart/recharts.ts b/benchmarks/conformance/cases/70-composed-chart/recharts.ts index a5ff8449..24a7d097 100644 --- a/benchmarks/conformance/cases/70-composed-chart/recharts.ts +++ b/benchmarks/conformance/cases/70-composed-chart/recharts.ts @@ -32,7 +32,7 @@ function chart(input: ConformanceInput) { margin: { top: 20, right: 20, bottom: 20, left: 20 }, accessibilityLayer: true, role: 'img', - title: 'Layered Seattle weather', + title: 'Seattle weather with three y axes', }, [ createElement(CartesianGrid, { @@ -47,14 +47,45 @@ function chart(input: ConformanceInput) { value instanceof Date ? dateFormat.format(value) : String(value), }), createElement(YAxis, { - key: 'y', + key: 'temperature-axis', + yAxisId: 'temperature', tickCount: 5, width: 60, + label: { + value: 'Temperature (°C)', + angle: -90, + position: 'insideLeft', + }, + }), + createElement(YAxis, { + key: 'precipitation-axis', + yAxisId: 'precipitation', + orientation: 'right', + tickCount: 5, + width: 72, + label: { + value: 'Precipitation (mm)', + angle: 90, + position: 'insideRight', + }, + }), + createElement(YAxis, { + key: 'wind-axis', + yAxisId: 'wind', + orientation: 'right', + tickCount: 5, + width: 60, + label: { + value: 'Wind (m/s)', + angle: 90, + position: 'insideRight', + }, }), createElement(Area, { key: 'area', type: 'monotone', dataKey: 'temp_max', + yAxisId: 'temperature', fill: '#8884d8', fillOpacity: 0.2, stroke: '#8884d8', @@ -63,6 +94,7 @@ function chart(input: ConformanceInput) { createElement(Bar, { key: 'bar', dataKey: 'precipitation', + yAxisId: 'precipitation', barSize: 20, fill: '#413ea0', isAnimationActive: false, @@ -71,6 +103,7 @@ function chart(input: ConformanceInput) { key: 'line', type: 'monotone', dataKey: 'temp_min', + yAxisId: 'temperature', stroke: '#ff7300', strokeWidth: 2, dot: false, @@ -79,6 +112,7 @@ function chart(input: ConformanceInput) { createElement(Scatter, { key: 'scatter', dataKey: 'wind', + yAxisId: 'wind', fill: '#ef4444', isAnimationActive: false, }), @@ -86,4 +120,4 @@ function chart(input: ConformanceInput) { ) } -export const mount = rechartsMount(chart, 'Layered Seattle weather') +export const mount = rechartsMount(chart, 'Seattle weather with three y axes') diff --git a/benchmarks/conformance/cases/70-composed-chart/tanstack.test.ts b/benchmarks/conformance/cases/70-composed-chart/tanstack.test.ts index 16733b7e..ec59bc74 100644 --- a/benchmarks/conformance/cases/70-composed-chart/tanstack.test.ts +++ b/benchmarks/conformance/cases/70-composed-chart/tanstack.test.ts @@ -2,7 +2,7 @@ import { createChartRuntime } from '@tanstack/charts' import { describe, expect, it } from 'vitest' import { loadTanStackSources } from '../../native-catalog' import { createExampleChart } from './tanstack' -import type { SceneNode } from '@tanstack/charts' +import type { SceneNode, SceneRule } from '@tanstack/charts' import type { ConformanceInput } from '../../types' const input = { @@ -42,6 +42,31 @@ describe('native composed-chart bar sizing', () => { }) }) + it('binds named scales and stacks both independent right-side axes', () => { + const scene = render(input) + const precipitationPoint = scene.points.find( + ({ markId }) => markId === 'precipitation-bars', + ) + const precipitationAxis = flatten(scene.nodes).find( + (node): node is SceneRule => + node.kind === 'rule' && node.key === 'precipitation-axis', + ) + const windAxis = flatten(scene.nodes).find( + (node): node is SceneRule => + node.kind === 'rule' && node.key === 'wind-axis', + ) + if (!precipitationPoint) { + throw new Error('Expected a precipitation point') + } + + expect(scene.scales.precipitation).toBeDefined() + expect(precipitationPoint.y).toBe( + scene.scales.precipitation?.map(precipitationPoint.yValue), + ) + expect(precipitationAxis?.x1).toBe(scene.chart.x + scene.chart.width) + expect(windAxis?.x1).toBeGreaterThan(precipitationAxis?.x1 ?? Infinity) + }) + it('does not hide responsive bar geometry outside the definition', async () => { const closure = await loadTanStackSources('70-composed-chart') const source = closure.files.map((file) => file.source).join('\n') @@ -49,6 +74,8 @@ describe('native composed-chart bar sizing', () => { expect(closure.files.map((file) => file.path)).toEqual(['example.tsx']) expect(closure.roles.support.files).toBe(0) expect(source).toContain('maxThickness: 20') + expect(source).toContain("yScale: 'precipitation'") + expect(source).toContain("yScale: 'wind'") expect(source).not.toContain('defineChart(({') expect(source).not.toContain('innerWidth') expect(source).not.toContain('categoryBandwidth') diff --git a/benchmarks/conformance/cases/70-composed-chart/tanstack.ts b/benchmarks/conformance/cases/70-composed-chart/tanstack.ts index 6c029e65..6b8596ee 100644 --- a/benchmarks/conformance/cases/70-composed-chart/tanstack.ts +++ b/benchmarks/conformance/cases/70-composed-chart/tanstack.ts @@ -3,6 +3,10 @@ import { tanstackExampleMount } from '../../shared/mount' export * from './example' -export const mount = tanstackExampleMount(createExampleChart, exampleAriaLabel) +export const mount = tanstackExampleMount( + createExampleChart, + exampleAriaLabel, + { guides: true, margin: true }, +) export const catalogCase = mount diff --git a/benchmarks/conformance/catalog-index.json b/benchmarks/conformance/catalog-index.json index 1360a775..9d3c84f0 100644 --- a/benchmarks/conformance/catalog-index.json +++ b/benchmarks/conformance/catalog-index.json @@ -2384,15 +2384,16 @@ "referenceRenderer": "recharts", "order": 700, "id": "70-composed-chart", - "title": "Layered Seattle weather chart", + "title": "Seattle weather with three y axes", "family": "composition", - "intent": "Compare daily maximum temperature, precipitation, minimum temperature, and wind using an area, bars, a line, and points.", + "intent": "Compare daily temperature, precipitation, and wind without forcing unlike units onto one y scale.", "support": "composed", "features": [ "mixed marks", + "independent y scales", + "left axis and stacked right axes", "daily observations", "monotone curves", - "shared numeric scale", "resolved maximum bar thickness" ], "geometry": [ @@ -2418,8 +2419,8 @@ "url": "https://recharts.github.io/en-US/examples/LineBarAreaComposedChart/" }, "ai": { - "create": "Create one chart from Seattle weather observations that layers maximum temperature as an area, precipitation as bars, minimum temperature as a monotone line, and wind as red points.", - "maintain": "Select a different weather window while preserving source dates and measures, mark order, colors, and cast-free channel inference." + "create": "Create one chart from Seattle weather observations that uses a left temperature axis, an independent right precipitation axis for bars, and a second right wind axis for points.", + "maintain": "Select a different weather window while preserving source dates, units, named scale bindings, stacked right axes, mark order, colors, and cast-free channel inference." }, "entries": { "example": "benchmarks/conformance/cases/70-composed-chart/example.tsx" diff --git a/benchmarks/conformance/previews/70-composed-chart.svg b/benchmarks/conformance/previews/70-composed-chart.svg index c4567dda..5de7df71 100644 --- a/benchmarks/conformance/previews/70-composed-chart.svg +++ b/benchmarks/conformance/previews/70-composed-chart.svg @@ -1 +1 @@ - + diff --git a/benchmarks/conformance/previews/manifest.json b/benchmarks/conformance/previews/manifest.json index 5175b615..0dc401fb 100644 --- a/benchmarks/conformance/previews/manifest.json +++ b/benchmarks/conformance/previews/manifest.json @@ -2,7 +2,7 @@ "schemaVersion": 1, "width": 288, "height": 192, - "sourceHash": "99fa46439aa2b513dc5c09e9bc5e9f4d7dacb18ed9e5f5d289df9d16082bb7fa", + "sourceHash": "77c9a85664a8a74ac8d3d00ebbdc9ff1be08ecd5859b962d16077cef8d996da0", "assets": [ { "id": "01-line-gaps", @@ -306,8 +306,8 @@ }, { "id": "70-composed-chart", - "sha256": "e67a703c89949a36f5b336a2095223a53e5b5a91a8a055868cb475a1a046003d", - "bytes": 4707 + "sha256": "642139631cae72ef76ff81e148e6d40e2ff83225a11b582a32878d0f166beae7", + "bytes": 14436 }, { "id": "71-recharts-population-pyramid", diff --git a/docs/config.json b/docs/config.json index 72d0734a..48e92d3f 100644 --- a/docs/config.json +++ b/docs/config.json @@ -545,7 +545,7 @@ "to": "/charts/catalog/charts/65-voronoi-nearest-tooltip/" }, { - "label": "Layered Seattle weather chart", + "label": "Seattle weather with three y axes", "to": "/charts/catalog/charts/70-composed-chart/" }, { diff --git a/docs/reference/scales-guides-and-color.md b/docs/reference/scales-guides-and-color.md index 1e3f5126..69af1cab 100644 --- a/docs/reference/scales-guides-and-color.md +++ b/docs/reference/scales-guides-and-color.md @@ -385,6 +385,8 @@ const chart = defineChart({ }) ``` + + A named scale must declare `channel: 'x'` or `channel: 'y'`. Its mark binding must use the same channel. The ID `color` is reserved for the shared visual color scale and cannot name a Cartesian position scale. diff --git a/examples/sandbox/src/App.tsx b/examples/sandbox/src/App.tsx index eb85c162..ce8e2035 100644 --- a/examples/sandbox/src/App.tsx +++ b/examples/sandbox/src/App.tsx @@ -16,6 +16,7 @@ import { import type { PenguinsRow } from '@tanstack/charts-data/penguins' import { createAgreementChart, + createAaplPriceVolumeChart, createCarEconomyChart, createIndustryChart, createPenguinChart, @@ -46,6 +47,13 @@ export function App() { svgAnimation: { duration: 800, easing: 'ease-out' }, }, ), + aaplPriceVolume: defineChart( + createAaplPriceVolumeChart({ rows: data.aapl }), + { + keyboard: false, + svgAnimation: { duration: 720, easing: 'ease-out' }, + }, + ), industries: defineChart( createIndustryChart({ rows: data.industries, @@ -469,6 +477,33 @@ export function App() { ))} + +
+ +
+ + + Close + + + + Volume + +
+
+
+ +
+
diff --git a/examples/sandbox/src/plots.ts b/examples/sandbox/src/plots.ts index b0ca61fb..a24bc2cb 100644 --- a/examples/sandbox/src/plots.ts +++ b/examples/sandbox/src/plots.ts @@ -21,6 +21,7 @@ import { scaleUtc, } from 'd3-scale' import { curveCatmullRom, curveMonotoneX } from 'd3-shape' +import type { AaplRow } from '@tanstack/charts-data/aapl' import type { PenguinsRow } from '@tanstack/charts-data/penguins' import type { SimpsonsRow } from '@tanstack/charts-data/simpsons' import type { @@ -122,6 +123,65 @@ export interface SparkInput { color: string } +export const createAaplPriceVolumeChart = (input: { + rows: readonly AaplRow[] +}) => + defineChart(({ width }) => ({ + marks: [ + areaY(input.rows, { + id: 'aapl-volume', + x: 'Date', + y1: 0, + y2: 'Volume', + yScale: 'volume', + fill: '#8579ff', + fillOpacity: 0.18, + curve: smooth, + }), + lineY(input.rows, { + id: 'aapl-close', + x: 'Date', + y: 'Close', + stroke: '#ff625a', + strokeWidth: 2, + curve: smooth, + }), + ], + scales: { + x: { + scale: scaleUtc, + axis: { + ticks: { + count: width < 680 ? 4 : 7, + format: formatYear, + }, + }, + }, + y: { + scale: scaleLinear, + nice: true, + grid: true, + axis: { + label: 'Close ($)', + ticks: { count: 4, format: formatDollars }, + }, + }, + volume: { + channel: 'y', + side: 'right', + scale: scaleLinear, + nice: true, + axis: { + label: 'Volume', + ticks: { count: 4, format: formatVolume }, + }, + }, + }, + clip: true, + margin: { top: 8, bottom: 30 }, + theme: chartTheme, + })) + export const createSparklineChart = (input: SparkInput) => { const [minimum, maximum] = extent(input.rows, input.value) const minValue = minimum ?? 0 @@ -602,6 +662,15 @@ function compactNumber(value: number): string { return `${Math.round(value)}` } +function formatDollars(value: number): string { + return `$${Math.round(value)}` +} + +function formatVolume(value: number): string { + if (value >= 1_000_000) return `${Math.round(value / 1_000_000)}M` + return compactNumber(value) +} + function formatMonth(value: Date): string { return value.toLocaleDateString('en-US', { month: 'short' }) } diff --git a/examples/sandbox/src/styles.css b/examples/sandbox/src/styles.css index 82a58602..88f8c37b 100644 --- a/examples/sandbox/src/styles.css +++ b/examples/sandbox/src/styles.css @@ -1042,6 +1042,10 @@ button { min-height: 322px; } +.multi-axis-card { + grid-column: 1 / -1; +} + .triage-chart { padding: 3px 16px 0; } diff --git a/packages/charts-core/docs/config.json b/packages/charts-core/docs/config.json index 72d0734a..48e92d3f 100644 --- a/packages/charts-core/docs/config.json +++ b/packages/charts-core/docs/config.json @@ -545,7 +545,7 @@ "to": "/charts/catalog/charts/65-voronoi-nearest-tooltip/" }, { - "label": "Layered Seattle weather chart", + "label": "Seattle weather with three y axes", "to": "/charts/catalog/charts/70-composed-chart/" }, { diff --git a/packages/charts-core/docs/reference/scales-guides-and-color.md b/packages/charts-core/docs/reference/scales-guides-and-color.md index 1e3f5126..69af1cab 100644 --- a/packages/charts-core/docs/reference/scales-guides-and-color.md +++ b/packages/charts-core/docs/reference/scales-guides-and-color.md @@ -385,6 +385,8 @@ const chart = defineChart({ }) ``` + + A named scale must declare `channel: 'x'` or `channel: 'y'`. Its mark binding must use the same channel. The ID `color` is reserved for the shared visual color scale and cannot name a Cartesian position scale. diff --git a/scripts/catalog-preview.mjs b/scripts/catalog-preview.mjs index 66489d5e..458e0b20 100644 --- a/scripts/catalog-preview.mjs +++ b/scripts/catalog-preview.mjs @@ -102,6 +102,7 @@ export const catalogGuidePreviewCaseIds = [ '120-themed-interactive-area', '121-active-bar-dashboard', '130-shadcn-radar-multiple', + '70-composed-chart', '80-echarts-axis-pointer', 'bar-horizontal-ranking', ] @@ -111,6 +112,7 @@ export const catalogMarginPreviewCaseIds = [ '118-token-usage-calendar', '128-shadcn-bar-multiple', '132-shadcn-tooltip-advanced', + '70-composed-chart', '80-echarts-axis-pointer', '81-recharts-interactive-legend', '88-echarts-free-cursor', @@ -126,6 +128,7 @@ export const catalogTextPreviewCaseIds = [ '36-hierarchy-tree', '58-select-extrema', '59-grouped-reducer-bars', + '70-composed-chart', '80-echarts-axis-pointer', '81-recharts-interactive-legend', '88-echarts-free-cursor', diff --git a/scripts/catalog-preview.test.mjs b/scripts/catalog-preview.test.mjs index aeea0f53..3bd65e21 100644 --- a/scripts/catalog-preview.test.mjs +++ b/scripts/catalog-preview.test.mjs @@ -175,6 +175,7 @@ describe('catalog previews', () => { '120-themed-interactive-area', '121-active-bar-dashboard', '130-shadcn-radar-multiple', + '70-composed-chart', '80-echarts-axis-pointer', 'bar-horizontal-ranking', ]) @@ -186,6 +187,7 @@ describe('catalog previews', () => { '118-token-usage-calendar', '128-shadcn-bar-multiple', '132-shadcn-tooltip-advanced', + '70-composed-chart', '80-echarts-axis-pointer', '81-recharts-interactive-legend', '88-echarts-free-cursor', @@ -201,6 +203,7 @@ describe('catalog previews', () => { '36-hierarchy-tree', '58-select-extrema', '59-grouped-reducer-bars', + '70-composed-chart', '80-echarts-axis-pointer', '81-recharts-interactive-legend', '88-echarts-free-cursor',