Column & Bar
Columns compare values across categories; the bar variant renders them horizontally (chart.type = "bar"). Grouping, stacking and percent stacking are one option away — no extra series math. Both variants are the same series type with flipped axes.
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: "column"
},
title: {
text: "Sales by region"
},
credits: {
enabled: false
},
colors: [
"#00968c",
"#06b6d4",
"#d97706",
"#7c3aed",
"#dc2626",
"#16a34a",
"#0172ad",
"#9333ea"
],
legend: {
enabled: true
},
xAxis: {
categories: [
"North",
"South",
"East",
"West"
]
},
yAxis: {
title: {
text: "Units"
}
},
plotOptions: {
column: {
borderRadius: 4,
pointPadding: 0.2
}
},
series: [
{
type: "column",
name: "2025",
data: [
140,
220,
180,
270
]
},
{
type: "column",
name: "2026",
data: [
180,
260,
210,
310
]
}
]
});
// render inside any mates template — give the wrapper a height:
export const MyChart = () =>
html`<div style="height: 22rem">${Chart(chart)}</div>`;
Live examples
Multiple series are grouped side-by-side per category automatically. chart.type = "column" is the vertical default.
import { html } from "mates";
import { Chart, chartAtom } from "mates-charts";
const chart = chartAtom({
chart: {
type: "column"
},
title: {
text: "Sales by region"
},
credits: {
enabled: false
},
colors: [
"#00968c",
"#06b6d4",
"#d97706",
"#7c3aed",
"#dc2626",
"#16a34a",
"#0172ad",
"#9333ea"
],
legend: {
enabled: true
},
xAxis: {
categories: [
"North",
"South",
"East",
"West"
]
},
yAxis: {
title: {
text: "Units"
}
},
plotOptions: {
column: {
borderRadius: 4,
pointPadding: 0.2
}
},
series: [
{
type: "column",
name: "2025",
data: [
140,
220,
180,
270
]
},
{
type: "column",
name: "2026",
data: [
180,
260,
210,
310
]
}
]
});
// render inside any mates template — give the wrapper a height:
export const MyChart = () =>
html`<div style="height: 22rem">${Chart(chart)}</div>`;
chart.type = "bar" flips orientation — great for long category labels that would overlap under vertical columns.
import { html } from "mates";
import { Chart, chartAtom } from "mates-charts";
const chart = chartAtom({
chart: {
type: "bar"
},
title: {
text: "Top features requested"
},
credits: {
enabled: false
},
colors: [
"#00968c",
"#06b6d4",
"#d97706",
"#7c3aed",
"#dc2626",
"#16a34a",
"#0172ad",
"#9333ea"
],
legend: {
enabled: false
},
xAxis: {
categories: [
"Dark mode",
"Exports",
"API keys",
"SSO",
"Audit log"
]
},
yAxis: {
title: {
text: "Votes"
}
},
plotOptions: {
bar: {
borderRadius: 4
}
},
series: [
{
type: "bar",
name: "Votes",
data: [
312,
254,
198,
142,
96
]
}
]
});
// render inside any mates template — give the wrapper a height:
export const MyChart = () =>
html`<div style="height: 22rem">${Chart(chart)}</div>`;
stacking = "normal" piles the series; a shared tooltip reads the total and every part at once.
import { html } from "mates";
import { Chart, chartAtom } from "mates-charts";
const chart = chartAtom({
chart: {
type: "column"
},
title: {
text: "Stacked revenue"
},
credits: {
enabled: false
},
colors: [
"#00968c",
"#06b6d4",
"#d97706",
"#7c3aed",
"#dc2626",
"#16a34a",
"#0172ad",
"#9333ea"
],
legend: {
enabled: true
},
xAxis: {
categories: [
"Q1",
"Q2",
"Q3",
"Q4"
]
},
yAxis: {
title: {
text: "$k"
}
},
tooltip: {
shared: true
},
plotOptions: {
column: {
stacking: "normal",
borderRadius: 3
},
series: {
dataLabels: {
enabled: true,
format: "{y}"
}
}
},
series: [
{
type: "column",
name: "Hardware",
data: [
60,
70,
65,
90
]
},
{
type: "column",
name: "Software",
data: [
40,
55,
60,
80
]
},
{
type: "column",
name: "Services",
data: [
20,
25,
35,
45
]
}
]
});
// render inside any mates template — give the wrapper a height:
export const MyChart = () =>
html`<div style="height: 22rem">${Chart(chart)}</div>`;
stacking = "percent" normalises each category to 100% — compare mix rather than magnitude.
import { html } from "mates";
import { Chart, chartAtom } from "mates-charts";
const chart = chartAtom({
chart: {
type: "column"
},
title: {
text: "Traffic mix by quarter"
},
credits: {
enabled: false
},
colors: [
"#00968c",
"#06b6d4",
"#d97706",
"#7c3aed",
"#dc2626",
"#16a34a",
"#0172ad",
"#9333ea"
],
legend: {
enabled: true
},
xAxis: {
categories: [
"Q1",
"Q2",
"Q3",
"Q4"
]
},
yAxis: {
labels: {
format: "{value}%"
},
max: 100,
title: {
text: ""
}
},
tooltip: {
shared: true,
valueSuffix: "%"
},
plotOptions: {
column: {
stacking: "percent",
borderRadius: 3
}
},
series: [
{
type: "column",
name: "Organic",
data: [
55,
52,
48,
45
]
},
{
type: "column",
name: "Paid",
data: [
25,
28,
32,
35
]
},
{
type: "column",
name: "Referral",
data: [
20,
20,
20,
20
]
}
]
});
// render inside any mates template — give the wrapper a height:
export const MyChart = () =>
html`<div style="height: 22rem">${Chart(chart)}</div>`;
Orientation and stacking compose freely — horizontal + normal stacking for survey results with many categories.
import { html } from "mates";
import { Chart, chartAtom } from "mates-charts";
const chart = chartAtom({
chart: {
type: "bar"
},
title: {
text: "Language usage by team"
},
credits: {
enabled: false
},
colors: [
"#00968c",
"#06b6d4",
"#d97706",
"#7c3aed",
"#dc2626",
"#16a34a",
"#0172ad",
"#9333ea"
],
legend: {
enabled: true
},
xAxis: {
categories: [
"Web",
"Mobile",
"Backend",
"Data"
]
},
yAxis: {
title: {
text: "Engineers"
}
},
tooltip: {
shared: true
},
plotOptions: {
bar: {
stacking: "normal",
borderRadius: 3
}
},
series: [
{
type: "bar",
name: "TypeScript",
data: [
12,
4,
6,
3
]
},
{
type: "bar",
name: "Kotlin",
data: [
0,
9,
1,
0
]
},
{
type: "bar",
name: "Go",
data: [
1,
0,
11,
4
]
},
{
type: "bar",
name: "Python",
data: [
2,
1,
3,
10
]
}
]
});
// render inside any mates template — give the wrapper a height:
export const MyChart = () =>
html`<div style="height: 22rem">${Chart(chart)}</div>`;
Negative values draw below/-left of the zero line automatically — perfect for profit/loss or sentiment. negativeColor highlights the losses.
import { html } from "mates";
import { Chart, chartAtom } from "mates-charts";
const chart = chartAtom({
chart: {
type: "column"
},
title: {
text: "Monthly net cash flow"
},
credits: {
enabled: false
},
colors: [
"#00968c",
"#06b6d4",
"#d97706",
"#7c3aed",
"#dc2626",
"#16a34a",
"#0172ad",
"#9333ea"
],
legend: {
enabled: false
},
xAxis: {
categories: [
"Jan",
"Feb",
"Mar",
"Apr",
"May",
"Jun"
]
},
yAxis: {
title: {
text: "$k"
},
plotLines: [
{
value: 0,
width: 1,
color: "#94a3b8"
}
]
},
plotOptions: {
column: {
borderRadius: 3,
negativeColor: "#dc2626"
}
},
series: [
{
type: "column",
name: "Net",
data: [
12,
-8,
15,
-4,
9,
21
]
}
]
});
// render inside any mates template — give the wrapper a height:
export const MyChart = () =>
html`<div style="height: 22rem">${Chart(chart)}</div>`;
dataLabels + borderRadius are the quickest route to the modern 'dashboard column' look.
import { html } from "mates";
import { Chart, chartAtom } from "mates-charts";
const chart = chartAtom({
chart: {
type: "column"
},
title: {
text: "Deploy frequency"
},
credits: {
enabled: false
},
colors: [
"#00968c",
"#06b6d4",
"#d97706",
"#7c3aed",
"#dc2626",
"#16a34a",
"#0172ad",
"#9333ea"
],
legend: {
enabled: false
},
xAxis: {
categories: [
"Mon",
"Tue",
"Wed",
"Thu",
"Fri"
]
},
yAxis: {
title: {
text: "Deploys"
},
maxPadding: 0.2
},
plotOptions: {
column: {
borderRadius: 6,
pointWidth: 28
},
series: {
dataLabels: {
enabled: true,
format: "{y}",
style: {
fontWeight: "600"
}
}
}
},
series: [
{
type: "column",
name: "Deploys",
data: [
14,
9,
22,
17,
11
]
}
]
});
// render inside any mates template — give the wrapper a height:
export const MyChart = () =>
html`<div style="height: 22rem">${Chart(chart)}</div>`;
When category values span orders of magnitude, a log y-axis keeps small bars visible next to giants.
import { html } from "mates";
import { Chart, chartAtom } from "mates-charts";
const chart = chartAtom({
chart: {
type: "column"
},
title: {
text: "Endpoints by traffic"
},
credits: {
enabled: false
},
colors: [
"#00968c",
"#06b6d4",
"#d97706",
"#7c3aed",
"#dc2626",
"#16a34a",
"#0172ad",
"#9333ea"
],
legend: {
enabled: false
},
xAxis: {
categories: [
"/",
"/api",
"/docs",
"/blog",
"/archive"
]
},
yAxis: {
type: "logarithmic",
title: {
text: "Requests / day (log)"
},
minorTickInterval: 0.1
},
series: [
{
type: "column",
name: "Requests",
data: [
980000,
410000,
42000,
3800,
210
]
}
]
});
// render inside any mates template — give the wrapper a height:
export const MyChart = () =>
html`<div style="height: 22rem">${Chart(chart)}</div>`;
Column categories descend into detail on click — the browser/OS drilldown pattern from the classic demo.
import "highcharts/modules/drilldown";
import { html } from "mates";
import { Chart, chartAtom } from "mates-charts";
const chart = chartAtom({
chart: {
type: "column"
},
title: {
text: "Browser usage — click a column"
},
credits: {
enabled: false
},
colors: [
"#00968c",
"#06b6d4",
"#d97706",
"#7c3aed",
"#dc2626",
"#16a34a",
"#0172ad",
"#9333ea"
],
legend: {
enabled: false
},
xAxis: {
type: "category"
},
yAxis: {
title: {
text: "Total percent market share"
}
},
plotOptions: {
series: {
borderWidth: 0,
dataLabels: {
enabled: true,
format: "{point.y:.1f}%"
}
}
},
series: [
{
type: "column",
name: "Browsers",
colorByPoint: true,
data: [
{
name: "Chrome",
y: 62,
drilldown: "chrome"
},
{
name: "Safari",
y: 24,
drilldown: "safari"
},
{
name: "Firefox",
y: 8,
drilldown: "firefox"
},
{
name: "Edge",
y: 6
}
]
}
],
drilldown: {
series: [
{
type: "column",
id: "chrome",
name: "Chrome",
data: [
[
"v126",
38
],
[
"v125",
14
],
[
"v124",
7
],
[
"Older",
3
]
]
},
{
type: "column",
id: "safari",
name: "Safari",
data: [
[
"v17",
15
],
[
"v16",
7
],
[
"Older",
2
]
]
},
{
type: "column",
id: "firefox",
name: "Firefox",
data: [
[
"v127",
5
],
[
"Older",
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 column & bar charts. See the full Highcharts API for everything else.
| Option | Type | Default | Description |
|---|---|---|---|
chart.type |
"column" | "bar" | — | Vertical columns or horizontal bars. |
plotOptions.column.stacking |
undefined | "normal" | "percent" | undefined | Stack series on top of each other or as a 100% share. |
plotOptions.column.grouping |
boolean | true | Group multiple series side-by-side per category. |
plotOptions.column.pointPadding |
number | 0.1 | Padding between columns (in category-width fractions). |
plotOptions.column.borderRadius |
number | 0 | Rounds the column tops. |
plotOptions.series.pointWidth |
number | undefined | Fixed bar width in pixels (overrides padding). |
plotOptions.series.dataLabels.enabled |
boolean | false | Print each value on its column. |
plotOptions.series.dataLabels.format |
string | "{y}" | Label format, e.g. "{y} kg" or "{point.name}: {y}". |
plotOptions.series.minPointLength |
number | 0 | Minimum pixel length so zero-values stay visible. |
plotOptions.series.negativeColor |
string | undefined | Colour for values below the threshold. |
yAxis.max |
number | auto | Pin the axis maximum — useful with stacking. |
yAxis.type |
"linear" | "logarithmic" | "linear" | Log scale for values spanning orders of magnitude. |