Pie & Donut
Pie charts show a part-of-whole split; innerSize turns one into a donut, and startAngle/endAngle bend it into a semi-circle. The packedbubble variant drops the axes entirely and clusters sized bubbles.
Usage
Create a chart atom with standard Highcharts options,
then render Chart(chart) anywhere in a
mates template. Every later chart.set(…) or
chart.update(…) re-renders the chart — no
imperative Highcharts code.
import { html } from "mates";
import { Chart, chartAtom } from "mates-charts";
const chart = chartAtom({
chart: {
type: "pie"
},
title: {
text: "Market share"
},
credits: {
enabled: false
},
colors: [
"#00968c",
"#06b6d4",
"#d97706",
"#7c3aed",
"#dc2626",
"#16a34a",
"#0172ad",
"#9333ea"
],
legend: {
enabled: false
},
plotOptions: {
pie: {
allowPointSelect: true,
cursor: "pointer",
dataLabels: {
enabled: true,
format: "<b>{point.name}</b>: {y}%"
},
showInLegend: true
}
},
series: [
{
type: "pie",
name: "Share",
data: [
[
"Chrome",
42
],
[
"Safari",
24
],
[
"Firefox",
18
],
[
"Edge",
11
],
[
"Other",
5
]
]
}
]
});
// render inside any mates template — give the wrapper a height:
export const MyChart = () =>
html`<div style="height: 22rem">${Chart(chart)}</div>`;
Live examples
dataLabels with {name} and {y} placeholders; allowPointSelect lets users pull slices out.
import { html } from "mates";
import { Chart, chartAtom } from "mates-charts";
const chart = chartAtom({
chart: {
type: "pie"
},
title: {
text: "Market share"
},
credits: {
enabled: false
},
colors: [
"#00968c",
"#06b6d4",
"#d97706",
"#7c3aed",
"#dc2626",
"#16a34a",
"#0172ad",
"#9333ea"
],
legend: {
enabled: false
},
plotOptions: {
pie: {
allowPointSelect: true,
cursor: "pointer",
dataLabels: {
enabled: true,
format: "<b>{point.name}</b>: {y}%"
},
showInLegend: true
}
},
series: [
{
type: "pie",
name: "Share",
data: [
[
"Chrome",
42
],
[
"Safari",
24
],
[
"Firefox",
18
],
[
"Edge",
11
],
[
"Other",
5
]
]
}
]
});
// render inside any mates template — give the wrapper a height:
export const MyChart = () =>
html`<div style="height: 22rem">${Chart(chart)}</div>`;
innerSize creates the hole; render the total in the middle with any absolutely-positioned element.
import { html } from "mates";
import { Chart, chartAtom } from "mates-charts";
const chart = chartAtom({
chart: {
type: "pie"
},
title: {
text: ""
},
credits: {
enabled: false
},
colors: [
"#00968c",
"#06b6d4",
"#d97706",
"#7c3aed",
"#dc2626",
"#16a34a",
"#0172ad",
"#9333ea"
],
legend: {
enabled: false
},
plotOptions: {
pie: {
innerSize: "62%",
borderWidth: 0,
borderRadius: 4,
dataLabels: {
enabled: true,
format: "{point.name} {y}%"
}
}
},
series: [
{
type: "pie",
name: "Spend",
data: [
[
"Cloud",
38
],
[
"Storage",
22
],
[
"Network",
18
],
[
"Security",
14
],
[
"Other",
8
]
]
}
]
});
// render inside any mates template — give the wrapper a height:
export const MyChart = () =>
html`<div style="height: 22rem">${Chart(chart)}</div>`;
startAngle = -90 and endAngle = 90 (with an innerSize hole) produce a half-donut gauge-style composition chart.
import { html } from "mates";
import { Chart, chartAtom } from "mates-charts";
const chart = chartAtom({
chart: {
type: "pie"
},
title: {
text: "Budget allocation",
align: "center",
verticalAlign: "bottom"
},
credits: {
enabled: false
},
colors: [
"#00968c",
"#06b6d4",
"#d97706",
"#7c3aed",
"#dc2626",
"#16a34a",
"#0172ad",
"#9333ea"
],
legend: {
enabled: false
},
plotOptions: {
pie: {
startAngle: -90,
endAngle: 90,
innerSize: "55%",
borderWidth: 0,
dataLabels: {
enabled: true,
format: "{point.name} {y}%"
}
}
},
series: [
{
type: "pie",
name: "Budget",
data: [
[
"R&D",
40
],
[
"Marketing",
25
],
[
"Ops",
20
],
[
"G&A",
15
]
]
}
]
});
// render inside any mates template — give the wrapper a height:
export const MyChart = () =>
html`<div style="height: 22rem">${Chart(chart)}</div>`;
showInLegend moves labels into a legend — the clean look for many small slices.
import { html } from "mates";
import { Chart, chartAtom } from "mates-charts";
const chart = chartAtom({
chart: {
type: "pie"
},
title: {
text: "Package downloads"
},
credits: {
enabled: false
},
colors: [
"#00968c",
"#06b6d4",
"#d97706",
"#7c3aed",
"#dc2626",
"#16a34a",
"#0172ad",
"#9333ea"
],
legend: {
enabled: true,
layout: "vertical",
align: "right",
verticalAlign: "middle"
},
plotOptions: {
pie: {
showInLegend: true,
dataLabels: {
enabled: false
},
borderWidth: 0
}
},
series: [
{
type: "pie",
name: "Downloads",
data: [
[
"mates",
84
],
[
"mates-ui",
61
],
[
"mates-charts",
37
],
[
"mates-icons",
29
],
[
"mates-ssg",
12
],
[
"mates-db",
7
]
]
}
]
});
// render inside any mates template — give the wrapper a height:
export const MyChart = () =>
html`<div style="height: 22rem">${Chart(chart)}</div>`;
Points carry an extra z dimension; the pie grows each slice radius with it. Requires the variable-pie module.
import "highcharts/modules/variable-pie";
import { html } from "mates";
import { Chart, chartAtom } from "mates-charts";
const chart = chartAtom({
chart: {
type: "variablepie"
},
title: {
text: "Countries: share vs population"
},
credits: {
enabled: false
},
colors: [
"#00968c",
"#06b6d4",
"#d97706",
"#7c3aed",
"#dc2626",
"#16a34a",
"#0172ad",
"#9333ea"
],
legend: {
enabled: false
},
plotOptions: {
variablepie: {
borderWidth: 0,
dataLabels: {
enabled: true,
format: "{point.name}"
}
}
},
series: [
{
type: "variablepie",
name: "Share",
variable: "z",
data: [
{
name: "Norway",
y: 34,
z: 5.5
},
{
name: "Germany",
y: 28,
z: 84
},
{
name: "Japan",
y: 22,
z: 123
},
{
name: "Brazil",
y: 16,
z: 216
}
]
}
]
});
// render inside any mates template — give the wrapper a height:
export const MyChart = () =>
html`<div style="height: 22rem">${Chart(chart)}</div>`;
The packedbubble series (ships in highcharts-more, auto-loaded by mates-charts) clusters bubbles without axes — great for tag clouds of quantities.
import { html } from "mates";
import { Chart, chartAtom } from "mates-charts";
const chart = chartAtom({
chart: {
type: "packedbubble"
},
title: {
text: "Skills in the ecosystem"
},
credits: {
enabled: false
},
colors: [
"#00968c",
"#06b6d4",
"#d97706",
"#7c3aed",
"#dc2626",
"#16a34a",
"#0172ad",
"#9333ea"
],
legend: {
enabled: false
},
yAxis: {
visible: false
},
plotOptions: {
packedbubble: {
minSize: "18%",
maxSize: "58%",
useSimulation: true,
dataLabels: {
enabled: true,
format: "{point.name}"
}
}
},
series: [
{
type: "packedbubble",
name: "Frontend",
data: [
{
name: "mates"
},
{
name: "lit-html"
},
{
name: "Highcharts"
},
{
name: "CSS"
}
]
},
{
type: "packedbubble",
name: "Tooling",
data: [
{
name: "Vite"
},
{
name: "TypeScript"
},
{
name: "Rollup"
}
]
}
]
});
// render inside any mates template — give the wrapper a height:
export const MyChart = () =>
html`<div style="height: 22rem">${Chart(chart)}</div>`;
Click a slice to descend into its sub-slices; a breadcrumb button appears to go back up. Sub-series are declared in drilldown.series.
import "highcharts/modules/drilldown";
import { html } from "mates";
import { Chart, chartAtom } from "mates-charts";
const chart = chartAtom({
chart: {
type: "pie"
},
title: {
text: "Spending by category — click to drill"
},
credits: {
enabled: false
},
colors: [
"#00968c",
"#06b6d4",
"#d97706",
"#7c3aed",
"#dc2626",
"#16a34a",
"#0172ad",
"#9333ea"
],
legend: {
enabled: false
},
plotOptions: {
pie: {
allowPointSelect: true,
cursor: "pointer",
dataLabels: {
enabled: true,
format: "{point.name}: {y}%"
}
}
},
series: [
{
type: "pie",
name: "Spend",
data: [
{
name: "Cloud",
y: 38,
drilldown: "cloud"
},
{
name: "Storage",
y: 22,
drilldown: "storage"
},
{
name: "Network",
y: 18
},
{
name: "Security",
y: 14
},
{
name: "Other",
y: 8
}
]
}
],
drilldown: {
series: [
{
type: "pie",
id: "cloud",
name: "Cloud",
data: [
[
"Compute",
22
],
[
"Kubernetes",
10
],
[
"Serverless",
6
]
]
},
{
type: "pie",
id: "storage",
name: "Storage",
data: [
[
"Object",
14
],
[
"Block",
5
],
[
"Backup",
3
]
]
}
]
}
});
// render inside any mates template — give the wrapper a height:
export const MyChart = () =>
html`<div style="height: 22rem">${Chart(chart)}</div>`;
Options reference
mates-charts passes options straight through to Highcharts — these are the keys that matter for pie & donut charts. See the full Highcharts API for everything else.
| Option | Type | Default | Description |
|---|---|---|---|
chart.type |
"pie" | "variablepie" | "packedbubble" | — | Classic slices, radius-sized slices, or axis-free bubble clusters. |
plotOptions.pie.innerSize |
string | number | 0 | Hole size for donuts — e.g. "60%" or pixels. |
plotOptions.pie.startAngle / endAngle |
number | 0 / 360 | Bend the pie into a semi-circle or arc. |
plotOptions.pie.allowPointSelect |
boolean | false | Let users click a slice to pull it out. |
plotOptions.pie.slicedOffset |
number | 10 | Pixel offset of selected slices. |
plotOptions.pie.dataLabels.enabled |
boolean | true | Print labels with connector lines. |
plotOptions.pie.dataLabels.format |
string | "{point.name}: {point.percentage:.1f}%" | Label template — {point.percentage:.1f} rounds to 1 decimal. |
plotOptions.pie.dataLabels.distance |
number | 30 | Label distance from the pie edge. |
plotOptions.pie.showInLegend |
boolean | false | Show slices in the legend instead of labels. |
series[].data |
[name, value][] | — | Tuples of label + value — the common pie data shape. |