Skip to main content

BarChart

BarChart

Compare categories with vertical or horizontal bars

Tags: chart comparison categories ranking

View Demo

The BarChart component excels at comparing discrete categories of data. It supports both vertical and horizontal orientations, stacked bars for showing composition, and value labels directly on the bars.

Reporting props marked Svelte only (valueFormat, showDataTable, exportable, reference lines, data zoom and so on) are available in @classic-homes/charts-svelte; React support is pending.

Import​

<script>
  import { BarChart } from '@classic-homes/charts-svelte';
</script>
// React
import { BarChart } from '@classic-homes/charts-react';

Basic Usage​

<script>
  import { BarChart } from '@classic-homes/charts-svelte';

  const data = {
    categories: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri'],
    series: [
      { name: 'Sales', data: [320, 332, 301, 334, 390] },
      { name: 'Returns', data: [120, 132, 101, 134, 90] },
    ],
  };
</script>

<BarChart title="Weekly Sales" {data} height={400} />

Props​

Chart-Specific Props​

Prop Type Default Description
data BarChartData required Chart data with categories and series
orientation 'vertical' | 'horizontal' 'vertical' Bar orientation. Horizontal bars list categories top to bottom in data order (the first category is at the top)
stacked boolean | 'percent' false Stack bars to show composition; 'percent' stacks each category's share of 100% (Svelte only)
showValues boolean false Show value labels on bars
showTotal boolean false Label each stack's total at the end of the bar, formatted with valueFormat; percent stacks show the raw total
rowHeight number 28 Height per category row when height="auto" on horizontal bars (Svelte only)
labelFormatter string | ((params: LabelFormatterParams) => string) - Data label template or function
xAxisConfig AxisConfig - Horizontal axis name, tick formatter, rotation and range
yAxisConfig AxisConfig - Vertical axis name, tick formatter, rotation and range
referenceLines ReferenceLine[] - Lines marking targets or statistics: { value: number | 'average' | 'median' | 'min' | 'max', label?, series?, style?, color? } (Svelte only)
referenceBands ReferenceBand[] - Shaded value ranges: { from, to, label?, color?, series? } (Svelte only)
dataZoom boolean | 'inside' | 'slider' - Zoom and pan the category axis: 'inside' (wheel and drag), 'slider', or true for both (Svelte only)
legend ChartLegendConfig - Built-in legend position, alignment, icon and formatter
onLegendChange (visible: Record<string, boolean>) => void - Called when legend items are shown or hidden
renderLegend Snippet<[LegendRenderProps]> - Custom HTML legend (e.g. ChartLegend) instead of the built-in one; React takes a function returning a node
onClick (params: DataPointEventParams) => void - Callback when a bar is clicked
onHover (params: DataPointEventParams) => void - Callback when hovering over a bar

Inherited Base Props​

Prop Type Default Description
title string required Chart title for accessibility
description string - Description for screen readers
height number | string 400 Chart height
theme 'light' | 'dark' | 'auto' 'auto' Theme preference
showLegend boolean true Show chart legend
showTooltip boolean true Show tooltip on hover
showGrid boolean true Show grid lines
tooltipFormatter string | ((items: TooltipFormatterParams[]) => string) - Custom tooltip template or HTML function
tooltipValueFormatter (value: number) => string - Format values in the default tooltip
option EChartsOption - Raw ECharts option deep-merged over the generated one
minHeight number - Minimum height in pixels; also bounds an 'auto' height
maxHeight number - Maximum height in pixels; also bounds an 'auto' height
loading boolean false Show loading skeleton; over existing data a loading overlay is shown instead (Svelte)
error string | null - Error message to display
onRetry () => void - Show a Retry button on the error state, calling this (Svelte only)
emptyMessage string - Message shown when data is empty
valueFormat ValueFormatPreset | Intl.NumberFormatOptions | ((value: number) => string) - How values are written in value axes, tooltips, labels and the data table: 'number', 'integer', 'compact', 'currency', 'currencyCents', 'percent', 'percentValue', 'days', Intl options or a function (Svelte only)
locale string 'en-US' Locale for valueFormat (Svelte only)
onReady (chart: EChartsType) => void - Called with the ECharts instance when it is created (Svelte only)
events Record<string, (params) => void> - Raw ECharts event handlers keyed by event name, e.g. datazoom (Svelte only)
showDataTable boolean | 'sr-only' 'sr-only' Render the data as a table: 'sr-only' for screen readers, true adds a visible "Show data" toggle, false for none (Svelte only)
exportable boolean | ChartExportConfig false Show PNG and CSV download buttons; or { image, csv, filename } (Svelte only)
patterns boolean false Fill series with decal patterns as well as colour, for colour-blind readers (Svelte only)
class string - Custom CSS class
animation boolean true Enable/disable animations (respects prefers-reduced-motion)

Data Structure​

interface BarChartData {
  categories: string[]; // Category labels
  series: Array<{
    name: string; // Series name for legend
    data: (number | null)[]; // Values for each category; null leaves a gap
    color?: string; // Optional custom color
    labels?: (string | null)[]; // Optional per-point label text
    stack?: string; // Stack group id; overrides `stacked` for this series
  }>;
}

Examples​

Horizontal Bar Chart​

Horizontal bars list categories top to bottom in data order, so a ranking sorted largest first reads from the top. (Earlier versions drew the first category at the bottom; if you reversed your data to compensate, stop reversing it.) With height="auto" the chart grows with its rows (rowHeight, bounded by minHeight/maxHeight). height="auto" is Svelte only.

<BarChart
  title="Closings by Builder"
  {data}
  orientation="horizontal"
  height="auto"
  rowHeight={32}
/>

Stacked Bar Chart​

<BarChart title="Revenue Breakdown" {data} stacked height={400} />

Stack Totals​

showTotal labels each stack's total at the end of the bar, formatted with valueFormat. Horizontal charts widen the right edge to fit the labels.

<BarChart
  title="Homes by Status"
  {data}
  stacked
  showTotal
  orientation="horizontal"
  valueFormat="integer"
/>

With Value Labels​

<BarChart title="Monthly Performance" {data} showValues height={400} />

Custom Labels and Axes​

Format data labels, name and rotate axes, and format tooltip values. Per-point labels annotate individual bars.

<script>
  import { BarChart } from '@classic-homes/charts-svelte';

  const data = {
    categories: ['Q1', 'Q2', 'Q3', 'Q4'],
    series: [
      { name: 'Revenue', data: [42000, 51000, 48000, 67000], labels: [null, null, null, 'Record'] },
    ],
  };
</script>

<BarChart
  title="Quarterly Revenue"
  {data}
  showValues
  labelFormatter={(p) => p.label ?? `$${p.value / 1000}k`}
  xAxisConfig={{ name: 'Quarter', rotate: 30 }}
  yAxisConfig={{ formatter: (v) => `$${Number(v) / 1000}k` }}
  tooltipValueFormatter={(v) => `$${v.toLocaleString()}`}
/>

Legend Placement​

<BarChart title="Weekly Sales" {data} legend={{ position: 'right', icon: 'circle' }} />

Custom Legend​

Render your own legend with the renderLegend snippet. ChartLegend is an accessible default (toggle buttons with aria-pressed); see ChartLegend.

<script>
  import { BarChart, ChartLegend } from '@classic-homes/charts-svelte';
</script>

{#snippet legend(props)}
  <ChartLegend {...props} />
{/snippet}

<BarChart title="Weekly Sales" {data} renderLegend={legend} legend={{ position: 'top' }} />
// React
<BarChart
  title="Weekly Sales"
  data={data}
  legend={{ position: 'top' }}
  renderLegend={(props) => <ChartLegend {...props} />}
/>

Raw ECharts Overrides​

Anything the props don't cover can be set with option, which is deep-merged over the generated ECharts option. Top-level arrays such as series merge by index.

<BarChart title="Weekly Sales" {data} option={{ series: [{ barWidth: 24 }], grid: { top: 40 } }} />

Percent Stacking and Stack Groups (Svelte only)​

stacked="percent" shows each category's share of 100%. A series' stack id groups it with other series that share the id, so you can stack some series and keep others side by side.

<BarChart title="Sales Mix by Community" {data} stacked="percent" />

<BarChart
  title="Starts and Closings"
  data={{
    categories: ['Q1', 'Q2'],
    series: [
      { name: 'Starts (spec)', data: [20, 24], stack: 'starts' },
      { name: 'Starts (to-be-built)', data: [31, 28], stack: 'starts' },
      { name: 'Closings', data: [44, 50] },
    ],
  }}
/>

Value Format and Average Line (Svelte only)​

<BarChart
  title="Revenue by Builder"
  {data}
  valueFormat="currency"
  referenceLines={[{ value: 'average', label: 'Average' }]}
/>

From Records (Svelte only)​

fromRecords pivots API rows into { categories, series }, with aggregation, sorting, top N and an "Other" bucket.

<script>
  import { BarChart, fromRecords } from '@classic-homes/charts-svelte';

  // rows: [{ builder: 'Classic Homes', status: 'Closed', homes: 12 }, ...]
  const data = fromRecords(rows, {
    category: 'builder',
    series: 'status',
    value: 'homes',
    sort: 'total',
    topN: 8,
    otherLabel: 'Other',
  });
</script>

<BarChart title="Homes by Builder" {data} orientation="horizontal" height="auto" stacked />

Accessibility​

  • The title prop is used as aria-label for screen readers
  • Animations respect prefers-reduced-motion media query
  • Color contrast maintained in light and dark modes
On this page