Intentwise Primitives

Charts

Full-featured data visualization components built on Recharts. Support multi-series, dual axes, auto-coloring from the design token palette, tooltips, legends, and PNG export.

AreaChart

Revenue & Ad Spend

Multi-series area chart with a dashed line for the secondary series.

Show code
const areaChartData = {
  "points": [
    {
      "timestamp": "Jan",
      "revenue": 420000,
      "adSpend": 52000
    },
    {
      "timestamp": "Feb",
      "revenue": 455000,
      "adSpend": 58000
    },
    {
      "timestamp": "Mar",
      "revenue": 510000,
      "adSpend": 63000
    },
    {
      "timestamp": "Apr",
      "revenue": 480000,
      "adSpend": 55000
    },
    {
      "timestamp": "May",
      "revenue": 530000,
      "adSpend": 61000
    },
    {
      "timestamp": "Jun",
      "revenue": 590000,
      "adSpend": 68000
    },
    {
      "timestamp": "Jul",
      "revenue": 620000,
      "adSpend": 72000
    },
    {
      "timestamp": "Aug",
      "revenue": 650000,
      "adSpend": 75000
    }
  ],
  "series": [
    {
      "key": "revenue",
      "label": "Revenue",
      "type": "area",
      "format": "currency",
      "yAxisId": "left"
    },
    {
      "key": "adSpend",
      "label": "Ad Spend",
      "type": "line",
      "format": "currency",
      "yAxisId": "left",
      "strokeDasharray": "5 5"
    }
  ],
  "xAxisKey": "timestamp"
};

<AreaChart data={areaChartData} title="Revenue & Ad Spend" height={350} exportable />

Dual Y-Axis

Two metrics on separate axes β€” revenue on the left, growth percentage on the right.

Show code
const dualAxisChartData = {
  "points": [
    {
      "timestamp": "Jan",
      "revenue": 420000,
      "growth": 8.2
    },
    {
      "timestamp": "Feb",
      "revenue": 455000,
      "growth": 10.5
    },
    {
      "timestamp": "Mar",
      "revenue": 510000,
      "growth": 12.1
    },
    {
      "timestamp": "Apr",
      "revenue": 480000,
      "growth": 9.3
    },
    {
      "timestamp": "May",
      "revenue": 530000,
      "growth": 11.8
    },
    {
      "timestamp": "Jun",
      "revenue": 590000,
      "growth": 14.2
    }
  ],
  "series": [
    {
      "key": "revenue",
      "label": "Revenue",
      "type": "area",
      "format": "currency",
      "yAxisId": "left"
    },
    {
      "key": "growth",
      "label": "Growth %",
      "type": "line",
      "format": "percent",
      "yAxisId": "right"
    }
  ],
  "xAxisKey": "timestamp",
  "yAxes": [
    {
      "id": "left",
      "format": "currency",
      "label": "Revenue"
    },
    {
      "id": "right",
      "format": "percent",
      "label": "Growth"
    }
  ]
};

<AreaChart data={dualAxisChartData} title="Revenue vs Growth" />

LineChart

Multi-Series Comparison

LineChart is a thin wrapper over the same time-series engine as AreaChart, without the area fill.

Show code
const dualAxisChartData = {
  "points": [
    {
      "timestamp": "Jan",
      "revenue": 420000,
      "growth": 8.2
    },
    {
      "timestamp": "Feb",
      "revenue": 455000,
      "growth": 10.5
    },
    {
      "timestamp": "Mar",
      "revenue": 510000,
      "growth": 12.1
    },
    {
      "timestamp": "Apr",
      "revenue": 480000,
      "growth": 9.3
    },
    {
      "timestamp": "May",
      "revenue": 530000,
      "growth": 11.8
    },
    {
      "timestamp": "Jun",
      "revenue": 590000,
      "growth": 14.2
    }
  ],
  "series": [
    {
      "key": "revenue",
      "label": "Revenue",
      "type": "area",
      "format": "currency",
      "yAxisId": "left"
    },
    {
      "key": "growth",
      "label": "Growth %",
      "type": "line",
      "format": "percent",
      "yAxisId": "right"
    }
  ],
  "xAxisKey": "timestamp",
  "yAxes": [
    {
      "id": "left",
      "format": "currency",
      "label": "Revenue"
    },
    {
      "id": "right",
      "format": "percent",
      "label": "Growth"
    }
  ]
};

<LineChart data={dualAxisChartData} title="Comparison" showDots />

BarChart

Grouped Bars

Side-by-side comparison of multiple metrics across categories.

Show code
const barChartData = {
  "points": [
    {
      "category": "Sponsored Products",
      "revenue": 300000,
      "adSpend": 50000
    },
    {
      "category": "Sponsored Brands",
      "revenue": 200000,
      "adSpend": 35000
    },
    {
      "category": "Sponsored Display",
      "revenue": 150000,
      "adSpend": 28000
    },
    {
      "category": "DSP",
      "revenue": 100000,
      "adSpend": 22000
    }
  ],
  "categoryKey": "category",
  "series": [
    {
      "key": "revenue",
      "label": "Revenue",
      "format": "currency"
    },
    {
      "key": "adSpend",
      "label": "Ad Spend",
      "format": "currency"
    }
  ]
};

<BarChart data={barChartData} title="Revenue by Ad Type" />

Stacked Bars

Use stackId on series to create stacked bar charts.

Show code
const stackedBarData = {
  "points": [
    {
      "category": "Q1",
      "organic": 200000,
      "sponsored": 300000
    },
    {
      "category": "Q2",
      "organic": 220000,
      "sponsored": 350000
    },
    {
      "category": "Q3",
      "organic": 250000,
      "sponsored": 380000
    },
    {
      "category": "Q4",
      "organic": 280000,
      "sponsored": 420000
    }
  ],
  "categoryKey": "category",
  "series": [
    {
      "key": "organic",
      "label": "Organic",
      "format": "currency",
      "stackId": "total"
    },
    {
      "key": "sponsored",
      "label": "Sponsored",
      "format": "currency",
      "stackId": "total"
    }
  ]
};

<BarChart data={stackedBarData} title="Revenue Composition" />

Horizontal Layout

Switch to horizontal bars with layout='horizontal' on the data.

Show code
const horizontalBarChartData = {
  "points": [
    {
      "category": "Sponsored Products",
      "revenue": 300000,
      "adSpend": 50000
    },
    {
      "category": "Sponsored Brands",
      "revenue": 200000,
      "adSpend": 35000
    },
    {
      "category": "Sponsored Display",
      "revenue": 150000,
      "adSpend": 28000
    },
    {
      "category": "DSP",
      "revenue": 100000,
      "adSpend": 22000
    }
  ],
  "categoryKey": "category",
  "series": [
    {
      "key": "revenue",
      "label": "Revenue",
      "format": "currency"
    },
    {
      "key": "adSpend",
      "label": "Ad Spend",
      "format": "currency"
    }
  ],
  "layout": "horizontal"
};

<BarChart data={horizontalBarChartData} />

With Bar Labels

Show formatted values above each bar.

Show code
const barChartData = {
  "points": [
    {
      "category": "Sponsored Products",
      "revenue": 300000,
      "adSpend": 50000
    },
    {
      "category": "Sponsored Brands",
      "revenue": 200000,
      "adSpend": 35000
    },
    {
      "category": "Sponsored Display",
      "revenue": 150000,
      "adSpend": 28000
    },
    {
      "category": "DSP",
      "revenue": 100000,
      "adSpend": 22000
    }
  ],
  "categoryKey": "category",
  "series": [
    {
      "key": "revenue",
      "label": "Revenue",
      "format": "currency"
    },
    {
      "key": "adSpend",
      "label": "Ad Spend",
      "format": "currency"
    }
  ]
};

<BarChart data={barChartData} showBarLabels />

Horizontal Bars with Labels

With layout='horizontal', showBarLabels places the formatted value at the end of each bar (to the right) instead of on top β€” vertical bars keep the top placement.

Show code
const horizontalBarChartData = {
  "points": [
    {
      "category": "Sponsored Products",
      "revenue": 300000,
      "adSpend": 50000
    },
    {
      "category": "Sponsored Brands",
      "revenue": 200000,
      "adSpend": 35000
    },
    {
      "category": "Sponsored Display",
      "revenue": 150000,
      "adSpend": 28000
    },
    {
      "category": "DSP",
      "revenue": 100000,
      "adSpend": 22000
    }
  ],
  "categoryKey": "category",
  "series": [
    {
      "key": "revenue",
      "label": "Revenue",
      "format": "currency"
    },
    {
      "key": "adSpend",
      "label": "Ad Spend",
      "format": "currency"
    }
  ],
  "layout": "horizontal"
};

<BarChart data={horizontalBarChartData} showBarLabels />

Customize the Y axis β€” detailed design (renderTick)

Name the axis you want to design β€” yAxis on a horizontal layout, where y holds the categories (xAxis on the default vertical one) β€” and pass renderTick to draw each tick yourself. It receives the category value, its resolved entity (image / title, read from imageKey / titleKey, default 'imageUrl' and 'title'), and the reserved block width and height; whatever it returns fills the block as ordinary HTML inside an SVG foreignObject, so design tokens and Tailwind classes work as usual. The detailed design below is that block, anatomy left to right / top to bottom: (1) a 40px rounded image thumbnail, falling back to a neutral placeholder when the point has no image; (2) the category code on the first line, bold, in the primary text token; (3) the entity title beneath it, one line in the muted token, truncated with an ellipsis when it overflows the reserved width. Hover a bar and the tooltip mirrors that same design on top of the metric details, above a divider β€” no extra wiring, it reuses the renderTick callback.

Show code
const productDetailsData = {
  "points": [
    {
      "asin": "B08N5WRWNW",
      "title": "Echo Dot (4th Gen) Smart Speaker with Alexa β€” Charcoal",
      "imageUrl": "data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.…",
      "adExposed": 182000,
      "organic": 96000
    },
    {
      "asin": "B09B8V1LZ3",
      "title": "Fire TV Stick 4K Max Streaming Device with Wi-Fi 6",
      "imageUrl": "data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.…",
      "adExposed": 154000,
      "organic": 88000
    },
    {
      "asin": "B07FZ8S74R",
      "title": "Echo Show 8 HD Smart Display with Alexa",
      "imageUrl": "data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.…",
      "adExposed": 121000,
      "organic": 74000
    },
    {
      "asin": "B0BDHWDR12",
      "title": "Kindle Paperwhite (16 GB) β€” Now with a 6.8\" Display",
      "imageUrl": "data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.…",
      "adExposed": 98000,
      "organic": 63000
    },
    {
      "asin": "B09WNK39JN",
      "title": "Ring Video Doorbell β€” 1080p HD Video, Improved Motion Detection",
      "imageUrl": "data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.…",
      "adExposed": 67000,
      "organic": 41000
    }
  ],
  "categoryKey": "asin",
  "series": [
    {
      "key": "adExposed",
      "label": "Ad-Exposed",
      "format": "currency"
    },
    {
      "key": "organic",
      "label": "Organic",
      "format": "currency"
    }
  ],
  "layout": "horizontal"
};

<BarChart
  data={productDetailsData}
  title="Top ASINs by Sales"
  height={460}
  showBarLabels
  yAxis={{
    width: 400,
    renderTick: ({ value, entity }) => (
      <div className="flex w-full items-center gap-3">
        {entity.image ? (
          <img
            src={entity.image}
            alt=""
            className="h-10 w-10 shrink-0 rounded-iw-md border border-iw-border object-cover"
          />
        ) : (
          <span className="h-10 w-10 shrink-0 rounded-iw-md border border-iw-border bg-iw-surface-secondary" />
        )}
        <span className="min-w-0 flex-1">
          <span className="block truncate text-sm font-semibold text-iw-text-primary">{value}</span>
          <span className="block truncate text-xs text-iw-text-muted">{entity.title}</span>
        </span>
      </div>
    ),
  }}
/>

Customize the X axis β€” detailed design (renderTick)

A vertical layout keeps its categories on the x-axis, so the same design goes on xAxis instead β€” the identical renderTick callback, unchanged. Only the anchoring differs: each block hangs under its tick, horizontally centred, and height reserves the axis band (72 by default). width sets each block's own width, so keep it near the category slot width to avoid neighbouring blocks overlapping. The tooltip mirrors the design the same way.

Show code
const verticalProductDetailsData = {
  "points": [
    {
      "asin": "B08N5WRWNW",
      "title": "Echo Dot (4th Gen) Smart Speaker with Alexa β€” Charcoal",
      "imageUrl": "data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.…",
      "adExposed": 182000,
      "organic": 96000
    },
    {
      "asin": "B09B8V1LZ3",
      "title": "Fire TV Stick 4K Max Streaming Device with Wi-Fi 6",
      "imageUrl": "data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.…",
      "adExposed": 154000,
      "organic": 88000
    },
    {
      "asin": "B07FZ8S74R",
      "title": "Echo Show 8 HD Smart Display with Alexa",
      "imageUrl": "data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.…",
      "adExposed": 121000,
      "organic": 74000
    },
    {
      "asin": "B0BDHWDR12",
      "title": "Kindle Paperwhite (16 GB) β€” Now with a 6.8\" Display",
      "imageUrl": "data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.…",
      "adExposed": 98000,
      "organic": 63000
    },
    {
      "asin": "B09WNK39JN",
      "title": "Ring Video Doorbell β€” 1080p HD Video, Improved Motion Detection",
      "imageUrl": "data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.…",
      "adExposed": 67000,
      "organic": 41000
    }
  ],
  "categoryKey": "asin",
  "series": [
    {
      "key": "adExposed",
      "label": "Ad-Exposed",
      "format": "currency"
    },
    {
      "key": "organic",
      "label": "Organic",
      "format": "currency"
    }
  ],
  "layout": "vertical"
};

<BarChart
  data={{ ...productDetailsData, layout: 'vertical' }}
  title="Top ASINs by Sales"
  height={460}
  xAxis={{ width: 210, height: 76, renderTick: detailedEntityTick }}
/>

DonutChart

Revenue Breakdown

Donut chart with center label showing total. Auto-colors from the design token palette.

Show code
const donutChartData = {
  "slices": [
    {
      "label": "Sponsored Products",
      "value": 52000
    },
    {
      "label": "Sponsored Brands",
      "value": 31000
    },
    {
      "label": "Sponsored Display",
      "value": 18000
    },
    {
      "label": "Organic",
      "value": 45000
    }
  ],
  "format": "currency",
  "centerLabel": "Total Revenue",
  "centerValue": 146000,
  "centerFormat": "currency"
};

<DonutChart data={donutChartData} />

ScatterChart

Ad Spend vs ROAS

Scatter plot for correlation analysis. Supports multiple series and bubble sizing.

Show code
const scatterChartData = {
  "points": [
    {
      "adSpend": 1200,
      "roas": 2.5
    },
    {
      "adSpend": 2400,
      "roas": 3.1
    },
    {
      "adSpend": 800,
      "roas": 1.8
    },
    {
      "adSpend": 3600,
      "roas": 4.2
    },
    {
      "adSpend": 5000,
      "roas": 3.5
    },
    {
      "adSpend": 1800,
      "roas": 2.9
    },
    {
      "adSpend": 4200,
      "roas": 3.8
    },
    {
      "adSpend": 600,
      "roas": 1.5
    },
    {
      "adSpend": 3000,
      "roas": 3.3
    },
    {
      "adSpend": 2200,
      "roas": 2.7
    }
  ],
  "series": [
    {
      "key": "campaigns",
      "label": "Campaigns",
      "xKey": "adSpend",
      "yKey": "roas"
    }
  ],
  "xFormat": "currency",
  "yFormat": "decimal",
  "xAxisLabel": "Ad Spend",
  "yAxisLabel": "ROAS"
};

<ScatterChart data={scatterChartData} />

FunnelChart

Purchase Funnel

Conversion funnel with stage-to-stage conversion rates. Built on Recharts FunnelChart.

Show code
const funnelChartData = {
  "stages": [
    {
      "name": "Impressions",
      "value": 100000
    },
    {
      "name": "Clicks",
      "value": 8000
    },
    {
      "name": "Add to Cart",
      "value": 2400
    },
    {
      "name": "Purchases",
      "value": 800
    }
  ],
  "format": "compact"
};

<FunnelChart data={funnelChartData} />

HeatMap

Clicks by Day & Hour

2D grid with color intensity based on values. Uses the sequential blue palette from design tokens.

Show code
const heatMapData = {
  "rows": [
    "Mon",
    "Tue",
    "Wed",
    "Thu",
    "Fri",
    "Sat",
    "Sun"
  ],
  "columns": [
    "9am",
    "10am",
    "11am",
    "12pm",
    "1pm",
    "2pm",
    "3pm",
    "4pm",
    "5pm"
  ],
  "cells": [
    {
      "row": "Mon",
      "column": "9am",
      "value": 50
    },
    {
      "row": "Mon",
      "column": "10am",
      "value": 163
    },
    {
      "row": "Mon",
      "column": "11am",
      "value": 156
    },
    {
      "row": "Mon",
      "column": "12pm",
      "value": 62
    },
    {
      "row": "Mon",
      "column": "1pm",
      "value": 22
    },
    {
      "row": "Mon",
      "column": "2pm",
      "value": 106
    },
    {
      "row": "Mon",
      "column": "3pm",
      "value": 223
    },
    {
      "row": "Mon",
      "column": "4pm",
      "value": 234
    },
    {
      "row": "Mon",
      "column": "5pm",
      "value": 133
    },
    {
      "row": "Tue",
      "column": "9am",
      "value": 179
    },
    {
      "row": "Tue",
      "column": "10am",
      "value": 223
    },
    {
      "row": "Tue",
      "column": "11am",
      "value": 143
    },
    {
      "row": "Tue",
      "column": "12pm",
      "value": 55
    },
    {
      "row": "Tue",
      "column": "1pm",
      "value": 79
    },
    {
      "row": "Tue",
      "column": "2pm",
      "value": 190
    },
    {
      "row": "Tue",
      "column": "3pm",
      "value": 245
    },
    {
      "row": "Tue",
      "column": "4pm",
      "value": 168
    },
    {
      "row": "Tue",
      "column": "5pm",
      "value": 48
    },
    {
      "row": "Wed",
      "column": "9am",
      "value": 247
    },
    {
      "row": "Wed",
      "column": "10am",
      "value": 202
    },
    {
      "row": "Wed",
      "column": "11am",
      "value": 86
    },
    {
      "row": "Wed",
      "column": "12pm",
      "value": 45
    },
    {
      "row": "Wed",
      "column": "1pm",
      "value": 123
    },
    {
      "row": "Wed",
      "column": "2pm",
      "value": 207
    },
    {
      "row": "Wed",
      "column": "3pm",
      "value": 175
    },
    {
      "row": "Wed",
      "column": "4pm",
      "value": 47
    },
    {
      "row": "Wed",
      "column": "5pm",
      "value": -36
    },
    {
      "row": "Thu",
      "column": "9am",
      "value": 223
    },
    {
      "row": "Thu",
      "column": "10am",
      "value": 109
    },
    {
      "row": "Thu",
      "column": "11am",
      "value": 12
    },
    {
      "row": "Thu",
      "column": "12pm",
      "value": 38
    },
    {
      "row": "Thu",
      "column": "1pm",
      "value": 132
    },
    {
      "row": "Thu",
      "column": "2pm",
      "value": 151
    },
    {
      "row": "Thu",
      "column": "3pm",
      "value": 47
    },
    {
      "row": "Thu",
      "column": "4pm",
      "value": -73
    },
    {
      "row": "Thu",
      "column": "5pm",
      "value": -79
    },
    {
      "row": "Fri",
      "column": "9am",
      "value": 117
    },
    {
      "row": "Fri",
      "column": "10am",
      "value": -12
    },
    {
      "row": "Fri",
      "column": "11am",
      "value": -44
    },
    {
      "row": "Fri",
      "column": "12pm",
      "value": 36
    },
    {
      "row": "Fri",
      "column": "1pm",
      "value": 103
    },
    {
      "row": "Fri",
      "column": "2pm",
      "value": 47
    },
    {
      "row": "Fri",
      "column": "3pm",
      "value": -80
    },
    {
      "row": "Fri",
      "column": "4pm",
      "value": -135
    },
    {
      "row": "Fri",
      "column": "5pm",
      "value": -62
    },
    {
      "row": "Sat",
      "column": "9am",
      "value": -20
    },
    {
      "row": "Sat",
      "column": "10am",
      "value": -103
    },
    {
      "row": "Sat",
      "column": "11am",
      "value": -56
    },
    {
      "row": "Sat",
      "column": "12pm",
      "value": 41
    },
    {
      "row": "Sat",
      "column": "1pm",
      "value": 49
    },
    {
      "row": "Sat",
      "column": "2pm",
      "value": -55
    },
    {
      "row": "Sat",
      "column": "3pm",
      "value": -146
    },
    {
      "row": "Sat",
      "column": "4pm",
      "value": -110
    },
    {
      "row": "Sat",
      "column": "5pm",
      "value": 8
    },
    {
      "row": "Sun",
      "column": "9am",
      "value": -124
    },
    {
      "row": "Sun",
      "column": "10am",
      "value": -122
    },
    {
      "row": "Sun",
      "column": "11am",
      "value": -18
    },
    {
      "row": "Sun",
      "column": "12pm",
      "value": 50
    },
    {
      "row": "Sun",
      "column": "1pm",
      "value": -5
    },
    {
      "row": "Sun",
      "column": "2pm",
      "value": -108
    },
    {
      "row": "Sun",
      "column": "3pm",
      "value": -119
    },
    {
      "row": "Sun",
      "column": "4pm",
      "value": -10
    },
    {
      "row": "Sun",
      "column": "5pm",
      "value": 98
    }
  ],
  "format": "number"
};

<HeatMap data={heatMapData} />

WaterfallChart

Revenue Waterfall

Cumulative bar chart showing increases and decreases. Green for gains, red for losses, blue for totals.

Show code
const waterfallData = {
  "steps": [
    {
      "name": "Gross Revenue",
      "value": 120000,
      "type": "total"
    },
    {
      "name": "Ad Spend",
      "value": 35000,
      "type": "decrease"
    },
    {
      "name": "COGS",
      "value": 28000,
      "type": "decrease"
    },
    {
      "name": "New Sales",
      "value": 15000,
      "type": "increase"
    },
    {
      "name": "Returns",
      "value": 8000,
      "type": "decrease"
    },
    {
      "name": "Net Revenue",
      "value": 64000,
      "type": "total"
    }
  ],
  "format": "currency"
};

<WaterfallChart data={waterfallData} />

RadarChart

Campaign Performance Radar

Multi-series radar (spider) chart for comparing performance profiles across dimensions. Supports configurable fill opacity and grid visibility.

Show code
const radarChartData = {
  "points": [
    {
      "axis": "ACoS",
      "campaign": 75,
      "benchmark": 60
    },
    {
      "axis": "CTR",
      "campaign": 82,
      "benchmark": 70
    },
    {
      "axis": "CVR",
      "campaign": 65,
      "benchmark": 55
    },
    {
      "axis": "Spend Efficiency",
      "campaign": 90,
      "benchmark": 80
    },
    {
      "axis": "ROAS",
      "campaign": 70,
      "benchmark": 65
    },
    {
      "axis": "Impression Share",
      "campaign": 85,
      "benchmark": 75
    }
  ],
  "series": [
    {
      "key": "campaign",
      "label": "Campaign A"
    },
    {
      "key": "benchmark",
      "label": "Benchmark",
      "fillOpacity": 0.1
    }
  ]
};

<RadarChart data={radarChartData} />

Without Grid Lines

Hide the polar grid for a cleaner look.

Show code
const radarChartData = {
  "points": [
    {
      "axis": "ACoS",
      "campaign": 75,
      "benchmark": 60
    },
    {
      "axis": "CTR",
      "campaign": 82,
      "benchmark": 70
    },
    {
      "axis": "CVR",
      "campaign": 65,
      "benchmark": 55
    },
    {
      "axis": "Spend Efficiency",
      "campaign": 90,
      "benchmark": 80
    },
    {
      "axis": "ROAS",
      "campaign": 70,
      "benchmark": 65
    },
    {
      "axis": "Impression Share",
      "campaign": 85,
      "benchmark": 75
    }
  ],
  "series": [
    {
      "key": "campaign",
      "label": "Campaign A"
    },
    {
      "key": "benchmark",
      "label": "Benchmark",
      "fillOpacity": 0.1
    }
  ]
};

<RadarChart data={radarChartData} showGrid={false} />

ComboChart

Bars + Line (Dual Axis)

ComboChart combines bars and lines on the same canvas with independent Y-axes β€” ideal for showing volume alongside a rate or percentage.

Show code
const comboChartData = {
  "points": [
    {
      "date": "Feb 23",
      "ordered_quantity": 20,
      "return_quantity": 2,
      "return_rate": 10
    },
    {
      "date": "Feb 24",
      "ordered_quantity": 25,
      "return_quantity": 1,
      "return_rate": 4
    },
    {
      "date": "Feb 25",
      "ordered_quantity": 15,
      "return_quantity": 0,
      "return_rate": 0
    },
    {
      "date": "Feb 26",
      "ordered_quantity": 30,
      "return_quantity": 0,
      "return_rate": 0
    },
    {
      "date": "Feb 27",
      "ordered_quantity": 12,
      "return_quantity": 0,
      "return_rate": 0
    },
    {
      "date": "Feb 28",
      "ordered_quantity": 35,
      "return_quantity": 5,
      "return_rate": 14.2
    },
    {
      "date": "Mar 01",
      "ordered_quantity": 28,
      "return_quantity": 2,
      "return_rate": 7.1
    },
    {
      "date": "Mar 02",
      "ordered_quantity": 22,
      "return_quantity": 0,
      "return_rate": 0
    },
    {
      "date": "Mar 03",
      "ordered_quantity": 18,
      "return_quantity": 0,
      "return_rate": 0
    },
    {
      "date": "Mar 04",
      "ordered_quantity": 24,
      "return_quantity": 0,
      "return_rate": 0
    },
    {
      "date": "Mar 05",
      "ordered_quantity": 40,
      "return_quantity": 4,
      "return_rate": 10
    },
    {
      "date": "Mar 06",
      "ordered_quantity": 32,
      "return_quantity": 0,
      "return_rate": 0
    },
    {
      "date": "Mar 07",
      "ordered_quantity": 26,
      "return_quantity": 2,
      "return_rate": 7.7
    },
    {
      "date": "Mar 08",
      "ordered_quantity": 30,
      "return_quantity": 2,
      "return_rate": 6.7
    }
  ],
  "xAxisKey": "date",
  "series": [
    {
      "key": "ordered_quantity",
      "label": "Ordered Quantity",
      "type": "bar",
      "yAxisId": "left",
      "format": "number"
    },
    {
      "key": "return_quantity",
      "label": "Returns Quantity",
      "type": "bar",
      "yAxisId": "left",
      "format": "number"
    },
    {
      "key": "return_rate",
      "label": "Return Rate",
      "type": "line",
      "yAxisId": "right",
      "format": "percent"
    }
  ],
  "yAxes": [
    {
      "id": "left",
      "label": "Quantity",
      "format": "number",
      "orientation": "left"
    },
    {
      "id": "right",
      "label": "Rate",
      "format": "percent",
      "orientation": "right"
    }
  ]
};

<ComboChart data={comboChartData} title="Orders & Return Rate" />

With Metric Chips

Shows the metric chips and Add Metric flow used in DSP-Order chart experiences.

Show code
const comboChartData = {
  "points": [
    {
      "date": "Feb 23",
      "ordered_quantity": 20,
      "return_quantity": 2,
      "return_rate": 10
    },
    {
      "date": "Feb 24",
      "ordered_quantity": 25,
      "return_quantity": 1,
      "return_rate": 4
    },
    {
      "date": "Feb 25",
      "ordered_quantity": 15,
      "return_quantity": 0,
      "return_rate": 0
    },
    {
      "date": "Feb 26",
      "ordered_quantity": 30,
      "return_quantity": 0,
      "return_rate": 0
    },
    {
      "date": "Feb 27",
      "ordered_quantity": 12,
      "return_quantity": 0,
      "return_rate": 0
    },
    {
      "date": "Feb 28",
      "ordered_quantity": 35,
      "return_quantity": 5,
      "return_rate": 14.2
    },
    {
      "date": "Mar 01",
      "ordered_quantity": 28,
      "return_quantity": 2,
      "return_rate": 7.1
    },
    {
      "date": "Mar 02",
      "ordered_quantity": 22,
      "return_quantity": 0,
      "return_rate": 0
    },
    {
      "date": "Mar 03",
      "ordered_quantity": 18,
      "return_quantity": 0,
      "return_rate": 0
    },
    {
      "date": "Mar 04",
      "ordered_quantity": 24,
      "return_quantity": 0,
      "return_rate": 0
    },
    {
      "date": "Mar 05",
      "ordered_quantity": 40,
      "return_quantity": 4,
      "return_rate": 10
    },
    {
      "date": "Mar 06",
      "ordered_quantity": 32,
      "return_quantity": 0,
      "return_rate": 0
    },
    {
      "date": "Mar 07",
      "ordered_quantity": 26,
      "return_quantity": 2,
      "return_rate": 7.7
    },
    {
      "date": "Mar 08",
      "ordered_quantity": 30,
      "return_quantity": 2,
      "return_rate": 6.7
    }
  ],
  "xAxisKey": "date",
  "series": [
    {
      "key": "ordered_quantity",
      "label": "Ordered Quantity",
      "type": "bar",
      "yAxisId": "left",
      "format": "number"
    },
    {
      "key": "return_quantity",
      "label": "Returns Quantity",
      "type": "bar",
      "yAxisId": "left",
      "format": "number"
    },
    {
      "key": "return_rate",
      "label": "Return Rate",
      "type": "line",
      "yAxisId": "right",
      "format": "percent"
    }
  ],
  "yAxes": [
    {
      "id": "left",
      "label": "Quantity",
      "format": "number",
      "orientation": "left"
    },
    {
      "id": "right",
      "label": "Rate",
      "format": "percent",
      "orientation": "right"
    }
  ]
};

<ComboChart
  data={comboChartData}
  enableMetricSelection
  availableMetrics={comboChartData.series}
  defaultVisibleMetrics={['ordered_quantity', 'return_rate']}
/>

Compare Mode

Pass compareData (previous-period points aligned by index) and an optional comparePeriodLabel. Dashed lines and translucent bars represent the previous period; the tooltip groups current vs previous entries.

Show code
const comboChartCompareData = {
  "points": [
    {
      "reportDate": "2026-03-25",
      "spend": 413.24,
      "revenue": 1171.18,
      "roas": 4.02
    },
    {
      "reportDate": "2026-03-26",
      "spend": 348.21,
      "revenue": 1731.77,
      "roas": 5.86
    },
    {
      "reportDate": "2026-03-27",
      "spend": 379.9,
      "revenue": 1738.13,
      "roas": 5.21
    },
    {
      "reportDate": "2026-03-28",
      "spend": 435.71,
      "revenue": 1358.46,
      "roas": 4.36
    },
    {
      "reportDate": "2026-03-29",
      "spend": 425.92,
      "revenue": 1523.24,
      "roas": 5.32
    },
    {
      "reportDate": "2026-03-30",
      "spend": 392.41,
      "revenue": 1166.25,
      "roas": 4.38
    },
    {
      "reportDate": "2026-03-31",
      "spend": 378.79,
      "revenue": 1023.53,
      "roas": 3.69
    },
    {
      "reportDate": "2026-04-01",
      "spend": 370.26,
      "revenue": 1635.12,
      "roas": 5.6
    },
    {
      "reportDate": "2026-04-02",
      "spend": 364.98,
      "revenue": 1126.02,
      "roas": 4.09
    },
    {
      "reportDate": "2026-04-03",
      "spend": 338.91,
      "revenue": 863.66,
      "roas": 2.85
    },
    {
      "reportDate": "2026-04-04",
      "spend": 432.41,
      "revenue": 1371.04,
      "roas": 4.85
    },
    {
      "reportDate": "2026-04-05",
      "spend": 392.28,
      "revenue": 886.67,
      "roas": 4.04
    },
    {
      "reportDate": "2026-04-06",
      "spend": 356.07,
      "revenue": 1327.18,
      "roas": 6.37
    }
  ],
  "xAxisKey": "reportDate",
  "series": [
    {
      "key": "spend",
      "label": "Spend",
      "type": "bar",
      "yAxisId": "left",
      "format": "currency",
      "strokeWidth": 2
    },
    {
      "key": "revenue",
      "label": "Revenue",
      "type": "line",
      "yAxisId": "left",
      "format": "currency",
      "strokeWidth": 2
    },
    {
      "key": "roas",
      "label": "ROAS",
      "type": "line",
      "yAxisId": "right",
      "format": "number",
      "strokeWidth": 2
    }
  ],
  "yAxes": [
    {
      "id": "left",
      "label": "Dollars",
      "format": "currency"
    },
    {
      "id": "right",
      "label": "ROAS",
      "format": "number"
    }
  ]
};

<ComboChart
  data={comboChartCompareData}
  compareData={comboChartComparePreviousPoints}
  comparePeriodLabel="Previous Period"
  title="Compare Mode β€” Campaigns"
/>

BiggestCampaignMovers

All Four Cards (Walmart Overview Layout)

Campaigns, Products, SP Keywords, and SB Keywords β€” the 2Γ—2 grid layout used on the Walmart overview page. Campaign rows show targeting type badges (SP A, SP KT, SB KT); products show item name as the sub-badge; keywords show match type (PHRASE, EXACT, BROAD).

Biggest Changes By Campaigns

CampaignDistributionImpact
SP-A-Whole Bean
SP A
24.1%+$136.0
SP-A-K-Cups-Products
SP A
82.7%+$504.0
SP-M-KT-NB-K-Cups
SP KT
32.1%+$190.0
SP-M-KT-Super Crema-Brand
SP KT
66.4%-$819.0
SP-M-KT-Super Crema-Non Brand
SP KT
22.0%-$119.0
Showing 1 to 5 of 7 campaigns

Biggest Changes By Products

ProductDistributionImpact
431148914
Lavazza Crema e Gusto Ground Coffee
4.5%+$27.0
518279618
Lavazza QualitΓ  Oro Whole Bean Coffee
21.0%-$126.0
14982973356
Lavazza Super Crema Whole Bean Coffee
44.0%+$213.0
1083192602
Lavazza Espresso Whole Bean Coffee
78.1%-$164.0
14982973357
Lavazza Super Crema Whole Bean 2.2lb
92.1%+$230.0
Showing 1 to 5 of 5 products

Biggest Changes By SP Keywords

KeywordDistributionImpact
super crema
PHRASE
32.0%-$173.0
k cup
PHRASE
14.5%-$70.0
lavazza
EXACT
38.2%-$480.0
whole bean coffee
BROAD
18.4%+$28.0
espresso beans
PHRASE
27.6%+$53.0
Showing 1 to 5 of 5 keywords

Biggest Changes By SB Keywords

KeywordDistributionImpact
lavazza
PHRASE
40.9%-$374.0
nespresso pods
PHRASE
12.3%+$89.0
espresso
EXACT
8.7%+$35.0
whole bean
BROAD
5.2%-$17.0
whole bean coffee
PHRASE
31.4%+$27.0
Showing 1 to 5 of 5 keywords
Show code
const campaignMoversData = {
  "items": [
    {
      "name": "SP-A-Whole Bean",
      "subLabel": "SP A",
      "changePercent": 24.1,
      "impact": 136
    },
    {
      "name": "SP-A-K-Cups-Products",
      "subLabel": "SP A",
      "changePercent": 82.7,
      "impact": 504
    },
    {
      "name": "SP-M-KT-NB-K-Cups",
      "subLabel": "SP KT",
      "changePercent": 32.1,
      "impact": 190
    },
    {
      "name": "SP-M-KT-Super Crema-Brand",
      "subLabel": "SP KT",
      "changePercent": -66.4,
      "impact": -819
    },
    {
      "name": "SP-M-KT-Super Crema-Non Brand",
      "subLabel": "SP KT",
      "changePercent": -22,
      "impact": -119
    },
    {
      "name": "SB-M-KT-Espresso-Brand",
      "subLabel": "SB KT",
      "changePercent": 14.2,
      "impact": 310
    },
    {
      "name": "SB-M-KT-Whole Bean Awareness",
      "subLabel": "SB KT",
      "changePercent": -8.3,
      "impact": -97
    }
  ],
  "format": "currency",
  "isIncreasePositive": true
};

<div className="grid grid-cols-2 gap-4">
  <BiggestCampaignMovers
    title="Biggest Changes By Campaigns"
    entityLabel="Campaign" itemNoun="campaigns"
    data={{ items: storyCampaignItems, format: 'currency', isIncreasePositive: true }}
    metrics={MOVERS_METRICS} selectedMetric="Ad Revenue"
  />
  <BiggestCampaignMovers
    title="Biggest Changes By Products"
    entityLabel="Product" itemNoun="products"
    data={{ items: storyProductItems, format: 'currency', isIncreasePositive: true }}
    metrics={MOVERS_METRICS} selectedMetric="Ad Revenue"
  />
  <BiggestCampaignMovers
    title="Biggest Changes By SP Keywords"
    entityLabel="Keyword" itemNoun="keywords"
    data={{ items: storySpKeywordItems, format: 'currency', isIncreasePositive: true }}
    metrics={MOVERS_METRICS} selectedMetric="Ad Revenue"
  />
  <BiggestCampaignMovers
    title="Biggest Changes By SB Keywords"
    entityLabel="Keyword" itemNoun="keywords"
    data={{ items: storySbKeywordItems, format: 'currency', isIncreasePositive: true }}
    metrics={MOVERS_METRICS} selectedMetric="Ad Revenue"
  />
</div>

BubbleChart

Spend vs ROAS

Bubble size encodes impressions. Useful for campaign efficiency maps.

Show code
const bubbleData = {
  "points": [
    {
      "x": 1000,
      "y": 2.5,
      "z": 50000,
      "label": "Campaign A"
    },
    {
      "x": 2000,
      "y": 3.1,
      "z": 80000,
      "label": "Campaign B"
    },
    {
      "x": 3000,
      "y": 2.8,
      "z": 120000,
      "label": "Campaign C"
    },
    {
      "x": 4000,
      "y": 4,
      "z": 150000,
      "label": "Campaign D"
    },
    {
      "x": 5000,
      "y": 3.5,
      "z": 200000,
      "label": "Campaign E"
    }
  ],
  "xFormat": "currency",
  "yFormat": "decimal",
  "zFormat": "compact",
  "xAxisLabel": "Ad Spend",
  "yAxisLabel": "ROAS",
  "zLabel": "Impressions"
};

<BubbleChart data={bubbleData} title="Spend vs ROAS" height={360} exportable />

Multi-Series

Color by series (Sponsored Products vs Sponsored Brands).

Show code
const multiSeriesBubbleData = {
  "points": [
    {
      "x": 1200,
      "y": 2.5,
      "z": 40000,
      "series": "sp",
      "label": "SP-1"
    },
    {
      "x": 2400,
      "y": 3.1,
      "z": 90000,
      "series": "sp",
      "label": "SP-2"
    },
    {
      "x": 800,
      "y": 1.8,
      "z": 20000,
      "series": "sb",
      "label": "SB-1"
    },
    {
      "x": 3600,
      "y": 4.2,
      "z": 130000,
      "series": "sb",
      "label": "SB-2"
    }
  ],
  "series": [
    {
      "key": "sp",
      "label": "Sponsored Products"
    },
    {
      "key": "sb",
      "label": "Sponsored Brands"
    }
  ],
  "xFormat": "currency",
  "yFormat": "decimal",
  "xAxisLabel": "Ad Spend",
  "yAxisLabel": "ROAS"
};

<BubbleChart data={multiSeriesBubbleData} title="By Ad Type" showLegend />

Quadrant with Reference Lines

Reference lines mark average units / sales for quadrant analysis.

Show code
const quadrantBubbleData = {
  "points": [
    {
      "x": 100,
      "y": 2.5,
      "z": 3000,
      "label": "ASIN-1"
    },
    {
      "x": 300,
      "y": 5,
      "z": 8000,
      "label": "ASIN-2"
    },
    {
      "x": 250,
      "y": 1.2,
      "z": 5000,
      "label": "ASIN-3"
    },
    {
      "x": 420,
      "y": 3.4,
      "z": 12000,
      "label": "ASIN-4"
    }
  ],
  "xAxisLabel": "Units",
  "yAxisLabel": "Sales",
  "xFormat": "integer",
  "yFormat": "currency",
  "referenceLines": [
    {
      "axis": "x",
      "value": 250,
      "label": "Avg Units"
    },
    {
      "axis": "y",
      "value": 3,
      "label": "Avg Sales"
    }
  ]
};

<BubbleChart data={quadrantBubbleData} title="ASIN Quadrants" />

MapChart

Regional Spend Choropleth

Geographic choropleth with optional proportional bubbles.

Show code
const mapChartData = {
  "regions": [
    {
      "isoCode": "US",
      "name": "United States",
      "value": 84500
    },
    {
      "isoCode": "MX",
      "name": "Mexico",
      "value": 12300
    },
    {
      "isoCode": "BR",
      "name": "Brazil",
      "value": 9800
    },
    {
      "isoCode": "FR",
      "name": "France",
      "value": 22100
    },
    {
      "isoCode": "ES",
      "name": "Spain",
      "value": 7600
    },
    {
      "isoCode": "IN",
      "name": "India",
      "value": 5400
    }
  ],
  "bubbles": [
    {
      "name": "California",
      "isoCode": "US",
      "value": 420000,
      "lat": 36.7,
      "lng": -119.4
    },
    {
      "name": "Texas",
      "isoCode": "US",
      "value": 260000,
      "lat": 31,
      "lng": -99.9
    },
    {
      "name": "Ontario",
      "isoCode": "CA",
      "value": 190000,
      "lat": 51.2,
      "lng": -85.3
    }
  ],
  "valueFormat": "currency"
};

<MapChart
  data={mapChartData}
  title="Ad Spend by Region"
  height={420}
/>

ContentScoreGauge

Content Score

Inline-SVG gauge for content quality scores (0–100).

Content Score

72
Good
Show code
<ContentScoreGauge score={72} rating="Good" title="Content Score" />

Goals Dashboard Variant

Shows percent-of-actual caption used on Goals dashboards.

Goal Progress

84%
of Actual
Show code
<ContentScoreGauge score={84} isGoalsDashboard hideExportButton />