Other
Chart
Dependency-free static SVG chart: line, area, bar, pie, donut, mixed (per-dataset marks), radar, scatter and heatmap. Accepts labels plus one or more datasets, colors series from the token palette and titles every point for hover tooltips.
Import
import { Chart } from "@zephora/react";Examples
Line and area
- Revenue
- Costs
const data = {
labels: ["Jan", "Feb", "Mar", "Apr", "May", "Jun"],
datasets: [
{ label: "Revenue", data: [12, 19, 14, 25, 22, 30] },
{ label: "Costs", data: [8, 11, 10, 14, 12, 16] },
],
};
<Chart type="line" data={data} />
<Chart type="area" data={data} showLegend={false} />Bar
Multiple datasets render as grouped bars per label.
- 2024
- 2025
<Chart
type="bar"
data={{
labels: ["Q1", "Q2", "Q3", "Q4"],
datasets: [
{ label: "2024", data: [40, 55, 48, 70] },
{ label: "2025", data: [52, 61, 66, 84] },
],
}}
/>Pie and donut
Radial charts read the first dataset and use one slice per label.
- Chrome
- Safari
- Firefox
- Edge
- Chrome
- Safari
- Firefox
- Edge
const data = {
labels: ["Chrome", "Safari", "Firefox", "Edge"],
datasets: [{ label: "Share", data: [62, 20, 10, 8] }],
};
<Chart type="pie" data={data} width={220} height={220} />
<Chart type="donut" data={data} width={220} height={220} />Mixed
`type="mixed"` lets every dataset pick its own mark via `kind` (default "bar"): bars split the group width between the bar datasets while line/area points sit at the middle of each label group so they align with the bars.
- Revenue
- Costs
- Margin %
<Chart
type="mixed"
data={{
labels: ["Q1", "Q2", "Q3", "Q4"],
datasets: [
{ label: "Revenue", data: [40, 55, 48, 70], kind: "bar" },
{ label: "Costs", data: [26, 30, 28, 38], kind: "bar" },
{ label: "Margin %", data: [35, 45, 42, 46], kind: "line" },
],
}}
/>Mixed dual axis
`yAxis="right"` (mixed only) scales a dataset against its own max instead of the shared left max — the right max is printed at the right edge. Ideal when a percentage series would otherwise flatten against large absolute values.
- Revenue
- Conversion %
<Chart
type="mixed"
data={{
labels: ["Q1", "Q2", "Q3", "Q4"],
datasets: [
{ label: "Revenue", data: [400, 550, 480, 700], kind: "bar" },
{ label: "Conversion %", data: [2.4, 3.1, 2.8, 3.6], kind: "line", yAxis: "right" },
],
}}
/>Radar
Each label becomes a spoke; every dataset draws a translucent polygon over the shared ring grid — ideal for comparing profiles across the same set of axes.
- Ada
- Kai
<Chart
type="radar"
data={{
labels: ["Speed", "Power", "Range", "Defense", "Stamina"],
datasets: [
{ label: "Ada", data: [80, 65, 90, 55, 70] },
{ label: "Kai", data: [60, 85, 55, 75, 80] },
],
}}
/>Scatter
Scatter datasets take explicit `{ x, y }` points (`ScatterPoint`); the x scale spans the min/max of all points. Plain numbers fall back to their index as x.
- Sample A
- Sample B
<Chart
type="scatter"
data={{
labels: [],
datasets: [
{
label: "Sample A",
data: [
{ x: 4, y: 12 }, { x: 9, y: 30 }, { x: 15, y: 22 },
{ x: 21, y: 45 }, { x: 28, y: 38 }, { x: 34, y: 52 },
],
},
{
label: "Sample B",
data: [
{ x: 6, y: 8 }, { x: 12, y: 18 }, { x: 18, y: 14 },
{ x: 24, y: 26 }, { x: 30, y: 21 }, { x: 36, y: 33 },
],
},
],
}}
/>Heatmap
Datasets are rows (the dataset label becomes the row label), labels are columns. Cell values map onto a five-step light-to-dark ramp of the primary token color; row/column labels render on the plot, so the legend is omitted.
<Chart
type="heatmap"
data={{
labels: ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"],
datasets: [
{ label: "Morning", data: [2, 5, 3, 8, 6, 1, 0] },
{ label: "Afternoon", data: [6, 9, 7, 12, 10, 4, 2] },
{ label: "Evening", data: [4, 7, 11, 9, 14, 8, 5] },
],
}}
/>API
Chart props
| Prop | Type | Default | Description |
|---|---|---|---|
type * | "line" | "area" | "bar" | "pie" | "donut" | "mixed" | "radar" | "scatter" | "heatmap" | — | Chart shape. "mixed" reads each dataset's `kind` for its mark. |
data * | { labels: string[]; datasets: ChartDataset[] } | — | Labels plus one or more datasets. Pie/donut read the first dataset. |
width | number | 480 | SVG width in px. |
height | number | 240 | SVG height in px. |
showLegend | boolean | true | Renders a legend under the chart. |
showGrid | boolean | true | Horizontal gridlines (line/area/bar only). |
strokeWidth | number | 2 | Line thickness for line/area charts. |
aria-label | string | — | Accessible chart summary; auto-generated from the type and dataset labels. |
unstyled | boolean | false | Headless mode — skips Zephora styling. |
ChartDataset props
| Prop | Type | Default | Description |
|---|---|---|---|
label * | string | — | Series name shown in the legend and point tooltips. |
data * | number[] | ScatterPoint[] | — | Series values. Scatter reads `{x, y}` points (plain numbers fall back to their index as x); every other type reads numbers (points read their y). |
color | string | — | Series color. Defaults to the token palette by dataset index. |
kind | "bar" | "line" | "area" | "bar" | Per-dataset mark used by type="mixed"; ignored by the other chart types. |
yAxis | "left" | "right" | "left" | Scale used by type="mixed": "right" datasets scale against their own max (shown at the right edge) instead of the shared left max. |
ScatterPoint props
| Prop | Type | Default | Description |
|---|---|---|---|
x * | number | — | Horizontal position; the x scale spans the min/max across all points. |
y * | number | — | Vertical value, scaled against the max across all datasets. |