Skip to main content

Component | Bar Chart

info

Introduced in SDK v0.25.0

Render a bar chart. Bar charts offer:

  • Aesthetic defaults for a clean, professional look.
  • Flexible customization options for orientation, scale, grouping, etc.
  • Built-in data transformation utilities for easy formatting.
  • Canvas rendering for efficient scaling to thousands of bars.
const salesData = [
{ month: "Jan", California: 95, Texas: 120, "New York": 310 },
{ month: "Feb", California: 105, Texas: 135, "New York": 290 },
/* ... */
{ month: "Dec", California: 250, Texas: 300, "New York": 520 },
];

page.add(() =>
ui.barChart("sales-chart", salesData, {
group: "month",
series: ["California", "Texas", "New York"],
groupMode: "grouped",
label: "Monthly Sales by Region",
})
);

Group rows

You'll likely need to re-format your data in order to chart it. Compose provides simple utilities to help you do this.

First, you'll need to group your data. For example, for a monthly chart, you'd group by month. Specify the group parameter to specify how rows in your data should be grouped:

  • A string key from your data
  • A function that receives each row and its index, returning a group label
  • If not provided, defaults to using the "group" key from your data
const salesData = [
{ date: "2023-01-15", product: "Laptop", revenue: 2500 },
{ date: "2023-02-22", product: "Monitor", revenue: 800 },
{ date: "2023-02-05", product: "Laptop", revenue: 2200 },
{ date: "2023-02-18", product: "Monitor", revenue: 900 },
{ date: "2023-03-10", product: "Laptop", revenue: 2800 },
{ date: "2023-03-25", product: "Monitor", revenue: 750 },
];

function getMonth(row) {
return new Date(row.date).toLocaleString('default', { month: 'long' });
}

page.add(() =>
ui.barChart("monthly-chart", salesData, {
group: (row) => getMonth(row), // Group the data by month
series: ["revenue"],
label: "Monthly Revenue"
})
);

Aggregate rows

Compose will aggregate rows with the same group value according to the aggregate parameter.

By default, the rows are aggregated by sum. You can also aggregate by count, average, min, or max.

const salesData = [
{ date: "2023-01-15", product: "Laptop", revenue: 2500 },
/* ... */
{ date: "2023-03-25", product: "Monitor", revenue: 750 },
];

function getMonth(row) {
return new Date(row.date).toLocaleString('default', { month: 'long' });
}

page.add(() =>
ui.barChart("monthly-chart", salesData, {
group: (row) => getMonth(row),
series: ["product"],
aggregate: "count", // Aggregate by count
label: "Products Sold by Month"
})
);

Segment within groups

Within each group, you can further segment your data by using the series parameter, which controls the bars that render for each group.

For example, you may want to break down your monthly sales by region.

Basic usage

You can pass a list of keys from your data to the series parameter, which will map to the bars that render for each group.

const salesData = [
{ month: "Jan", California: 95, Texas: 120, "New York": 310 },
{ month: "Feb", California: 105, Texas: 135, "New York": 290 },
/* ... */
{ month: "Dec", California: 250, Texas: 300, "New York": 520 },
];

page.add(() =>
ui.barChart("sales-chart", salesData, {
group: "month",
series: ["California", "Texas"]
groupMode: "grouped",
label: "Monthly Sales by Region",
})
);

Advanced usage

Alternatively, you can pass an object with configuration properties to further customize the series.

Each object must have a value property that can be either a key from your data or a function that receives each row and returns a numeric value.

const salesData = [
{ month: "Jan", California: 95, Texas: 120, "New York": 310 },
{ month: "Feb", California: 105, Texas: 135, "New York": 290 },
/* ... */
{ month: "Dec", California: 250, Texas: 300, "New York": 520 },
];

page.add(() =>
ui.barChart("sales-chart", salesData, {
group: "month",
series: [
{
label: "Midwest",
value: (row) => row.California + row.Texas
}
],
groupMode: "grouped",
label: "Monthly Sales by Region",
})
);

Series object properties

value

required string | (row: DataRow, idx: number) => number | null | undefined

The row's value to be used for the series. Either:

  • A string that maps to a key in the data.
  • A function that receives each row and its index and returns a numeric value. You can also return null or undefined to exclude the row from the dataset.

The returned value will be aggregated by group (e.g. if you are grouping data by month, all rows for a month will be aggregated together).


label

optional string
The label to use for the series in the legend, tooltips, etc.

aggregate

optional string literal

The aggregate function to be used for the series. Use this if you want this series to be aggregated differently than the others.

Options: sum, count, average, min, max.

Defaults to the chart-level aggregate function (which itself defaults to sum).


Kitchen sink example

The example below demonstrates how to create a bar chart with dynamic series and custom grouping.

const PRODUCT_TO_COST = {
"Laptop": 1000,
"Monitor": 500,
"Keyboard": 100,
}

const PRODUCTS_LIST = Object.keys(PRODUCT_TO_COST);

const salesData = [
{ date: "2023-01-15", product: "Laptop", },
{ date: "2023-02-22", product: "Monitor", },
{ date: "2023-02-05", product: "Keyboard", },
/* ... */
{ date: "2023-02-18", product: "Monitor", },
{ date: "2023-03-10", product: "Laptop", },
{ date: "2023-03-25", product: "Monitor", },
];

function getMonth(row) {
return new Date(row.date).toLocaleString('default', { month: 'short', year: '2-digit' });
}

page.add(() =>
ui.barChart("monthly-chart", salesData, {
group: (row) => getMonth(row), // Group the data by month
series: PRODUCTS_LIST.map(product => ({
label: product,
value: (row) => {
if (row.product === product) {
return PRODUCT_TO_COST[product];
}
return 0;
}
})),
label: "Monthly Revenue by Product"
})
);

API reference

Function signature

type DataRow = Record<string, any>

ui.barChart<T extends DataRow>(
id: string,
data: T[]
properties?: Partial<{
group: string | ((row: T, idx: number) => string | null | undefined),
series: Array<string | SeriesObject<T>>,
aggregate: "sum" | "count" | "average" | "min" | "max",
groupMode: "grouped" | "stacked",
label: string,
description: string,
orientation: "horizontal" | "vertical",
scale: "linear" | "symlog",
style: Style,
}>
)

Parameters

id

required string
A unique identifier for the component. This is necessary so that Compose can properly pass user actions back to the component.

data

required DataRow[]
The data to be displayed in the bar chart.

properties.group

optional string | ((row: DataRow, idx: number) => string | null | undefined)

How to group the data. If not provided, Compose will look for a key named group in the data.

Learn more in the group rows section.


properties.series

optional Array<string | SeriesObject>

The series to be displayed in the bar chart. If not provided, Compose will use all keys found in the first row of the data (excluding the group key) as separate series.

Learn more in the series section.


properties.aggregate

optional string literal

How to aggregate rows that are in the same group. Choose from sum, count, average, min, or max.

Defaults to sum.

Learn more in the aggregate rows section.


properties.groupMode

optional string literal

How to display the bars within each group. Either:

  • grouped: Display the bars side-by-side.
  • stacked: Stack the bars on top of each other.

Defaults to stacked.


properties.label

optional string

The label to display above the bar chart. If not provided, the label will be inferred from the id.


properties.description

optional string

A description to display between the label and bar chart.


properties.orientation

optional string literal

The orientation of the bar chart. Either:

  • horizontal: Display the bars horizontally.
  • vertical: Display the bars vertically.

Defaults to vertical.


properties.scale

optional string literal

How to scale the value axis. Either:

  • linear: Scale linearly. Best for most cases.
  • symlog: Scale logarithmically. Best for cases where data differs by orders of magnitude.

Defaults to linear.


properties.style

optional Style

Directly style the underlying element using CSS. See the styling guide for more details on available style properties.