Bar
Grouped bars
Multiple series against shared categories render as grouped bars. Bar charts default to a per-mark tooltip; this one opts into tooltip: { shared: true } because readers compare the three series within a quarter.
ts
import { createChart } from '@chartcraft/core';
const chart = createChart(document.querySelector<HTMLElement>('#chart')!, {
type: 'bar',
title: 'Revenue by quarter',
subtitle: 'FY2025, USD millions',
data: {
categories: ['Q1', 'Q2', 'Q3', 'Q4'],
series: [
{ id: 'product', name: 'Product', data: [12.4, 13.1, 14.8, 16.2] },
{ id: 'services', name: 'Services', data: [6.1, 6.4, 7.0, 7.9] },
{ id: 'licensing', name: 'Licensing', data: [2.8, 3.0, 3.1, 3.6] },
],
},
yAxis: { label: 'USD (millions)' },
tooltip: { shared: true },
a11y: {
description:
'All three revenue lines grew each quarter of FY2025; product revenue led, ending at 16.2 million USD in Q4.',
},
});vue
<script setup lang="ts">
import { BarChart } from '@chartcraft/vue';
import type { ChartSpec } from '@chartcraft/vue';
const options: ChartSpec = {
title: 'Revenue by quarter',
subtitle: 'FY2025, USD millions',
data: {
categories: ['Q1', 'Q2', 'Q3', 'Q4'],
series: [
{ id: 'product', name: 'Product', data: [12.4, 13.1, 14.8, 16.2] },
{ id: 'services', name: 'Services', data: [6.1, 6.4, 7.0, 7.9] },
{ id: 'licensing', name: 'Licensing', data: [2.8, 3.0, 3.1, 3.6] },
],
},
yAxis: { label: 'USD (millions)' },
tooltip: { shared: true },
a11y: {
description:
'All three revenue lines grew each quarter of FY2025; product revenue led, ending at 16.2 million USD in Q4.',
},
};
</script>
<template>
<BarChart :options="options" style="height: 340px" />
</template>Horizontal bars
horizontal: true puts categories on the y-axis — the right form for long category labels. With a single series the legend hides automatically; the title names the measure.
ts
import { createChart } from '@chartcraft/core';
const chart = createChart(document.querySelector<HTMLElement>('#chart')!, {
type: 'bar',
horizontal: true,
title: 'Support tickets by category',
subtitle: 'Open tickets, this week',
data: {
categories: [
'Billing & invoicing',
'Account access',
'API & integrations',
'Performance',
'Feature requests',
'Other',
],
series: [{ id: 'tickets', name: 'Open tickets', data: [64, 51, 43, 28, 19, 12] }],
},
xAxis: { label: 'Tickets' },
a11y: {
description:
'Billing and invoicing leads open support tickets this week with 64, followed by account access with 51.',
},
});vue
<script setup lang="ts">
import { BarChart } from '@chartcraft/vue';
import type { ChartSpec } from '@chartcraft/vue';
const options: ChartSpec = {
horizontal: true,
title: 'Support tickets by category',
subtitle: 'Open tickets, this week',
data: {
categories: [
'Billing & invoicing',
'Account access',
'API & integrations',
'Performance',
'Feature requests',
'Other',
],
series: [{ id: 'tickets', name: 'Open tickets', data: [64, 51, 43, 28, 19, 12] }],
},
xAxis: { label: 'Tickets' },
a11y: {
description:
'Billing and invoicing leads open support tickets this week with 64, followed by account access with 51.',
},
};
</script>
<template>
<BarChart :options="options" style="height: 340px" />
</template>Bar baselines anchor at 0 when the data is non-negative — truncating a bar axis misrepresents magnitude, so a truncated min must always be explicit (Scales and axes).