Bar
A bar series represents values as bars, making it easy to compare categories
and see their relative sizes. Use a categorical field on one axis and a numeric
field on the other. Categories on x produce vertical bars, while categories
on y produce horizontal bars.
Rounded bars and data colors
Set corner rounding and spacing independently. A color accessor highlights days with more than 80 requests per second.
const data = [ { day: 'Mon', requests: 42 }, { day: 'Tue', requests: 68 }, { day: 'Wed', requests: 91 }, { day: 'Thu', requests: 57 }, { day: 'Fri', requests: 84 }, { day: 'Sat', requests: 36 }, { day: 'Sun', requests: 24 }, ]
const rounded_bars = plot({ series: [plot.bar({ data, x: 'day', y: 'requests', border_radius: 6, inset: 5, color: pure(row => Number(row.requests) > 80 ? { light: '#c2410c', dark: '#fdba74' } : { light: '#0891b2', dark: '#67e8f9' }), hover_span_x: true, tooltip: pure(({ x, y }) => h("span", {}, x + ': ' + y + ' requests/s')), })], height: 260, margin: { top: 5, right: 8, bottom: 20, left: 30 }, axis: { x: { label: '' }, y: { min: 0, max: 100, label: '' } }, background: { light: '#ffffff', dark: '#151b28' }, chrome_color: { light: '#e2e8f0', dark: '#334155' }, grid: { x: false, y: true }, border: false, zoom_pan: false, })
// In Antithesis notebook, plot() returns a Printable. Uncomment below to display it: // print(rounded_bars) // presentation.blank("Rounded bars").print(rounded_bars)Horizontal bars
Place categories on the y-axis to leave room for their names. Hover anywhere along a category’s row to inspect its value.
const data = [ { service: 'Search', requests: 92 }, { service: 'Feed', requests: 78 }, { service: 'Checkout', requests: 64 }, { service: 'Profile', requests: 47 }, { service: 'Upload', requests: 31 }, ]
const horizontal_bars = plot({ series: [plot.bar({ data, x: 'requests', y: 'service', border_radius: 4, inset: 8, color: { light: '#7c3aed', dark: '#c4b5fd' }, hover_span_y: true, tooltip: pure(({ x, y }) => h("span", {}, y + ': ' + x + ' requests/s')), })], height: 260, margin: { top: 5, right: 12, bottom: 20, left: 78 }, axis: { x: { min: 0, max: 100, label: '' }, y: { label: '' } }, background: { light: '#ffffff', dark: '#151b28' }, chrome_color: { light: '#e2e8f0', dark: '#334155' }, grid: { x: true, y: false }, border: false, zoom_pan: false, })
// In Antithesis notebook, plot() returns a Printable. Uncomment below to display it: // print(horizontal_bars) // presentation.blank("Horizontal bars").print(horizontal_bars)Positive and negative values
Bars extend from zero in either direction. Use a color accessor to distinguish monthly gains from losses.
const data = [ { month: 'Jan', change: 24 }, { month: 'Feb', change: -16 }, { month: 'Mar', change: 38 }, { month: 'Apr', change: 12 }, { month: 'May', change: -28 }, { month: 'Jun', change: -9 }, { month: 'Jul', change: 31 }, ]
const diverging_bars = plot({ series: [plot.bar({ data, x: 'month', y: 'change', inset: 6, color: pure(row => Number(row.change) >= 0 ? { light: '#0d9488', dark: '#5eead4' } : { light: '#c2410c', dark: '#fdba74' }), hover_span_x: true, tooltip: pure(({ x, y }) => h("span", {}, x + ': ' + (Number(y) > 0 ? '+' : '') + y + '%')), })], height: 260, margin: { top: 5, right: 8, bottom: 20, left: 30 }, axis: { x: { label: '' }, y: { min: -40, max: 40, label: '' } }, background: { light: '#ffffff', dark: '#151b28' }, chrome_color: { light: '#e2e8f0', dark: '#334155' }, grid: { x: false, y: true }, border: false, zoom_pan: false, })
// In Antithesis notebook, plot() returns a Printable. Uncomment below to display it: // print(diverging_bars) // presentation.blank("Diverging bars").print(diverging_bars)Custom category order
Set axis.x.categories to order bars by severity, independently of the source row order.
const data = [ { severity: 'High', count: 28 }, { severity: 'Low', count: 46 }, { severity: 'Critical', count: 12 }, { severity: 'Medium', count: 35 }, ]
const category_order = plot({ series: [plot.bar({ data, x: 'severity', y: 'count', inset: 10, border_radius: 3, color: { light: '#64748b', dark: '#94a3b8' }, tooltip: pure(({ x, y }) => h("span", {}, x + ': ' + y + ' issues')), })], height: 260, margin: { top: 5, right: 12, bottom: 24, left: 30 }, axis: { x: { categories: ['Critical', 'High', 'Medium', 'Low'], label: '' }, y: { min: 0, max: 50, label: '' }, }, background: { light: '#ffffff', dark: '#151b28' }, chrome_color: { light: '#e2e8f0', dark: '#334155' }, grid: { x: false, y: true }, border: false, zoom_pan: false, })
// In Antithesis notebook, plot() returns a Printable. Uncomment below to display it: // print(category_order) // presentation.blank("Category order").print(category_order)Bar arguments
| Field | Type | Default | Description |
|---|---|---|---|
data |
{[key: string]: any}[] |
Required | Data points to plot. |
x? |
FieldArg | string[] |
'x' |
Category or value field. An array of value fields creates horizontal stacks. |
y? |
FieldArg | string[] |
'y' |
Category or value field. An array of value fields creates vertical stacks. |
color? |
ColorArg or ThemeColor[] |
Black | Uniform or per-row color. A color array maps to stacked fields in order. |
border_radius? |
number |
0 |
Bar corner radius in pixels. |
inset? |
number |
1/6 of band width | Space left on each side within a categorical band, in pixels. |
min_size? |
number |
2 |
Minimum rendered value length in pixels. |
hover_span_x? |
boolean |
false |
Extend the area that responds to tooltips, selection, and hover highlights along the x axis. |
hover_span_y? |
boolean |
false |
Extend the area that responds to tooltips, selection, and hover highlights along the y axis. |
tooltip? |
TooltipArg |
None | Use true for the default tooltip, or a callback for custom content. |
on_select? |
SelectFn |
None | Callback receiving the selected point and its source data. |
hoverable? |
boolean |
true |
Enable tooltips, selection callbacks, and hover highlights for this series. |
highlight? |
boolean |
true |
Highlight a data point when you hover over it. |
highlight_color? |
ColorArg |
Automatic | Exact hover color, including opacity. Stacked bars also accept a ThemeColor[] palette. |
This example draws a bar for each group using its count, rounds the corners, and adds tooltips and a selection callback.
const selected_data = new reactive.StateVar('Select a point to inspect its data.')
const series = [plot.bar({ data: [{ group: 'A', count: 8 }, { group: 'B', count: 12 }], x: 'group', y: 'count', color: { light: 'steelblue', dark: 'lightskyblue' }, border_radius: 3, inset: 4, min_size: 2, hover_span_x: true, hover_span_y: false, tooltip: pure(({ x, y }) => h("span", {}, `(${x}, ${y})`)), on_select: pure(({ row }) => selected_data.set(JSON.stringify(row)), { selected_data }), hoverable: true, highlight: true, })]
const bar_options_plot = plot({ series, height: 260 })
const bar_options = h( 'div', {}, bar_options_plot, h( pure(({ selected_data }) => h('output', { 'aria-live': 'polite', style: { display: 'block' } }, selected_data.get()), ), { selected_data }, ), )
// In Antithesis notebook, plot() returns a Printable. Uncomment below to display it: // print(bar_options) // presentation.blank("Bar options").print(bar_options)Stacked bars
Stacked bars divide each bar into segments, showing how individual values
contribute to a total. They make it easy to compare both the totals and their
composition across categories. Pass an array of value-field names to y for
vertical stacks or x for horizontal stacks. An array of colors assigns one
color to each field, in the same order.
Stacked values
Pass multiple value fields to stack them within each category. Colors follow the field order; hover a segment to see its contribution.
const data = [ { day: 'Mon', network: 18, compute: 42, storage: 24 }, { day: 'Tue', network: 24, compute: 32, storage: 18 }, { day: 'Wed', network: 12, compute: 56, storage: 28 }, { day: 'Thu', network: 28, compute: 24, storage: 16 }, { day: 'Fri', network: 16, compute: 48, storage: 22 }, ]
const stacked_bars = plot({ series: [plot.bar({ data, x: 'day', y: ['network', 'compute', 'storage'], color: [ { light: '#0d9488', dark: '#5eead4' }, { light: '#6366f1', dark: '#a5b4fc' }, { light: '#d97706', dark: '#fcd34d' }, ], inset: 8, tooltip: pure(({ label, y }) => h("span", {}, label + ': ' + y + ' ms')), })], height: 260, margin: { top: 5, right: 8, bottom: 20, left: 30 }, axis: { x: { label: '' }, y: { min: 0, max: 100, label: '' } }, background: { light: '#ffffff', dark: '#151b28' }, chrome_color: { light: '#e2e8f0', dark: '#334155' }, grid: { x: false, y: true }, border: false, zoom_pan: false, })
// In Antithesis notebook, plot() returns a Printable. Uncomment below to display it: // print(stacked_bars) // presentation.blank("Stacked bars").print(stacked_bars)Horizontal stacks
Pass multiple fields to x and categories to y to compare contributions across services.
const data = [ { service: 'Search', network: 18, compute: 46, storage: 14 }, { service: 'Feed', network: 26, compute: 28, storage: 22 }, { service: 'Upload', network: 42, compute: 16, storage: 32 }, { service: 'Export', network: 12, compute: 36, storage: 18 }, ]
const horizontal_stacks = plot({ series: [plot.bar({ data, x: ['network', 'compute', 'storage'], y: 'service', color: [ { light: '#0d9488', dark: '#5eead4' }, { light: '#6366f1', dark: '#a5b4fc' }, { light: '#d97706', dark: '#fcd34d' }, ], inset: 8, border_radius: 3, tooltip: pure(({ label, x }) => h("span", {}, label + ': ' + x + ' ms')), })], height: 260, margin: { top: 5, right: 8, bottom: 20, left: 64 }, axis: { x: { min: 0, max: 100, label: '' }, y: { label: '' } }, background: { light: '#ffffff', dark: '#151b28' }, chrome_color: { light: '#e2e8f0', dark: '#334155' }, grid: { x: true, y: false }, border: false, zoom_pan: false, })
// In Antithesis notebook, plot() returns a Printable. Uncomment below to display it: // print(horizontal_stacks) // presentation.blank("Horizontal stacks").print(horizontal_stacks)Positive and negative stacks
Positive and negative values stack separately from zero. Each segment retains its sign and field label.
const data = [ { month: 'Jan', new: 28, expansion: 12, churn: -14, contraction: -6 }, { month: 'Feb', new: 18, expansion: 8, churn: -22, contraction: -10 }, { month: 'Mar', new: 36, expansion: 16, churn: -8, contraction: -4 }, { month: 'Apr', new: 24, expansion: 18, churn: -18, contraction: -12 }, { month: 'May', new: 32, expansion: 10, churn: -12, contraction: -8 }, ]
const diverging_stacks = plot({ series: [plot.bar({ data, x: 'month', y: ['new', 'expansion', 'churn', 'contraction'], color: [ { light: '#0d9488', dark: '#2dd4bf' }, { light: '#5eead4', dark: '#99f6e4' }, { light: '#ea580c', dark: '#fb923c' }, { light: '#fdba74', dark: '#fed7aa' }, ], inset: 7, tooltip: pure(({ label, y }) => h("span", {}, label + ': ' + (Number(y) > 0 ? '+' : '') + y)), })], height: 260, margin: { top: 5, right: 8, bottom: 20, left: 36 }, axis: { x: { label: '' }, y: { min: -40, max: 60, label: '' } }, background: { light: '#ffffff', dark: '#151b28' }, chrome_color: { light: '#e2e8f0', dark: '#334155' }, grid: { x: false, y: true }, border: false, zoom_pan: false, })
// In Antithesis notebook, plot() returns a Printable. Uncomment below to display it: // print(diverging_stacks) // presentation.blank("Diverging stacks").print(diverging_stacks)Full-stack tooltips
Hover a segment to see every value in its stack. The callback reads the values from row and uses label to display the hovered segment’s name and value in bold.
const data = [ { day: 'Mon', network: 18, compute: 42, storage: 24 }, { day: 'Tue', network: 24, compute: 32, storage: 18 }, { day: 'Wed', network: 12, compute: 56, storage: 28 }, { day: 'Thu', network: 28, compute: 24, storage: 16 }, { day: 'Fri', network: 16, compute: 48, storage: 22 }, ]
const stack_tooltips = plot({ series: [plot.bar({ data, x: 'day', y: ['network', 'compute', 'storage'], color: [ { light: '#0d9488', dark: '#5eead4' }, { light: '#6366f1', dark: '#a5b4fc' }, { light: '#d97706', dark: '#fcd34d' }, ], inset: 10, hover_span_x: false, hover_span_y: false, tooltip: pure(({ label, row }) => { return h('div', {}, ...['network', 'compute', 'storage'].map(field => h('div', {}, h(field === label ? 'strong' : 'span', {}, field + ': ' + row[field] + ' ms')))) }), })], height: 260, margin: { top: 5, right: 8, bottom: 20, left: 30 }, axis: { x: { label: '' }, y: { min: 0, max: 100, label: '' } }, background: { light: '#ffffff', dark: '#151b28' }, chrome_color: { light: '#e2e8f0', dark: '#334155' }, grid: { x: false, y: true }, border: false, zoom_pan: false, })
// In Antithesis notebook, plot() returns a Printable. Uncomment below to display it: // print(stack_tooltips) // presentation.blank("Stack tooltips").print(stack_tooltips)This example stacks passed and failed counts within each group, assigns a color to each segment, and adds tooltips and a selection callback.
const selected_data = new reactive.StateVar('Select a point to inspect its data.')
const series = [plot.bar({ data: [ { group: 'A', passed: 8, failed: 2 }, { group: 'B', passed: 12, failed: 3 }, ], x: 'group', y: ['passed', 'failed'], color: ['seagreen', 'coral'], border_radius: 3, inset: 4, min_size: 2, hover_span_x: true, hover_span_y: false, tooltip: pure(({ label, y }) => h("span", {}, `${label}: ${y}`)), on_select: pure(({ row }) => selected_data.set(JSON.stringify(row)), { selected_data }), hoverable: true, highlight: true, })]
const stacked_options_plot = plot({ series, height: 260 })
const stacked_options = h( 'div', {}, stacked_options_plot, h( pure(({ selected_data }) => h('output', { 'aria-live': 'polite', style: { display: 'block' } }, selected_data.get()), ), { selected_data }, ), )
// In Antithesis notebook, plot() returns a Printable. Uncomment below to display it: // print(stacked_options) // presentation.blank("Stacked options").print(stacked_options)Shared configuration
See Install and configure to set up Plot. The argument tables describe omitted fields; examples may override these defaults. See Data fields, Series colors, Strokes, and Mark shapes for shared options. For callbacks, see Tooltips and Selection.