Bar Chart

A responsive bar chart with vertical and horizontal layouts, stacked and percentage modes, interactive legend, and click events on bars and categories. Powered by Recharts, inspired by Tremor.

Basic

A single-category bar chart with a value formatter.

Multi-Category

Multiple categories rendered side by side with distinct colors and a shared legend.

Stacked

Bars stacked on top of each other to show cumulative totals.

Percent Stacked

Stacked bars normalized to 100% to show relative proportions across categories.

Vertical

Horizontal bars — ideal for long category labels like region names.

Vertical Stacked

Horizontal stacked bars for comparing multi-category totals across groups.

Interactive

Click a bar or legend item to select it. Click again or click the background to deselect.

onValueChange: null

Custom Formatting

Custom colors, no legend, and wider bar gaps via barCategoryGap.

Auto-Scale Labels

Use autoScaleLabels to automatically shrink tick font size as entries grow — no scroll or truncation needed for large datasets.

Label Truncation & Scroll

For datasets with very long label strings, use labelTruncateAt to clip them to a fixed character limit — the full label is still shown in the tooltip via tooltipFullLabel. Pair with minBarSize and maxHeight to cap the chart height and make it scrollable, guaranteeing each bar stays readable regardless of how many entries there are.

BarChart

A responsive bar chart with horizontal and vertical layouts, stacked and percentage modes, interactive legend, and click events on bars and categories. Powered by Recharts, inspired by Tremor.

Usage

import { BarChart } from "@/components/charts/bar-chart"

// Basic
<BarChart
  data={data}
  index="month"
  categories={["Sales"]}
  valueFormatter={(v) => `$${v.toLocaleString()}`}
/>

// Stacked
<BarChart
  data={data}
  index="month"
  categories={["Engineering", "Marketing", "Support"]}
  type="stacked"
/>

// Vertical (horizontal bars)
<BarChart
  data={data}
  index="region"
  categories={["Revenue"]}
  layout="vertical"
  valueFormatter={(v) => `$${v.toLocaleString()}`}
/>

// Interactive
<BarChart
  data={data}
  index="month"
  categories={["Engineering", "Marketing", "Support"]}
  onValueChange={(v) => console.log(v)}
/>

BarChart Props

PropTypeDefaultDescription
data*Record<string, any>[]Array of data objects. Each object should have the index key and one key per category.
index*stringThe key in each data object used as the category-axis label (e.g. "month", "region").
categories*string[]Array of data keys to render as bar series.
colorsChartColor[]CHART_COLORSColor palette for each category. Cycles if fewer colors than categories.
valueFormatter(value: number) => stringv => v.toString()Formats Y-axis ticks and tooltip values.
layout"vertical" | "horizontal""horizontal"Orientation of the chart. "horizontal" renders vertical bars; "vertical" renders horizontal bars.
type"default" | "stacked" | "percent""default"Bar display mode. "default" = side-by-side, "stacked" = stacked, "percent" = stacked normalized to 100%.
barCategoryGapstring | numberGap between bar groups. Accepts a percentage string (e.g. "20%") or pixel value.
showXAxisbooleantrueShow or hide the X-axis.
showYAxisbooleantrueShow or hide the Y-axis.
showGridLinesbooleantrueShow or hide background grid lines.
yAxisWidthnumberWidth in pixels reserved for the Y-axis. Auto-inferred from data if omitted.
xAxisLabelstringOptional label rendered below the X-axis.
yAxisLabelstringOptional label rendered to the left of the Y-axis, rotated 90°.
axisTextSize"xs" | "sm" | "md" | "lg" | number"xs"Font size for axis tick labels.
autoScaleLabelsbooleanfalseAutomatically shrinks axis tick font size as entry count grows, preventing label overlap on large datasets without needing scroll.
tickGapnumber5Minimum gap in pixels between X-axis ticks.
startEndOnlybooleanfalseOnly show the first and last tick labels on the category axis.
intervalType"preserveStartEnd" | "equidistantPreserveStart""equidistantPreserveStart"Recharts tick interval strategy for the category axis.
allowDecimalsbooleantrueAllow decimal values on the numeric axis.
autoMinValuebooleanfalseUse "auto" for the numeric axis minimum instead of 0.
minValuenumberExplicit minimum for the numeric axis.
maxValuenumberExplicit maximum for the numeric axis.
showLegendbooleantrueShow or hide the legend.
legendPosition"left" | "center" | "right""right"Horizontal alignment of the legend.
enableLegendSliderbooleanfalseMakes the legend horizontally scrollable with arrow buttons when items overflow.
legendTextSize"xs" | "sm" | "md" | "lg" | number"xs"Font size for legend labels.
showTooltipbooleantrueShow or hide the tooltip on hover.
tooltipCallback(content: TooltipProps) => voidCallback fired whenever the tooltip active state or label changes.
customTooltipReact.ComponentType<TooltipProps>Custom tooltip component. Receives active, payload, and label props.
roundedbooleanfalseApply rounded corners to bars.
labelTruncateAtnumberTruncate axis labels at this many characters, appending "...". When omitted, labels are shown in full.
minBarSizenumberMinimum pixels per bar row in vertical layout. When set, chart height is computed as data.length × minBarSize. Has no effect in horizontal layout.
maxHeightnumber | stringCaps the outer container height and enables vertical scrolling when the computed height (from minBarSize) exceeds this value.
tooltipFullLabelbooleantrueWhen true the tooltip shows the full label text. Set to false to show the truncated label (requires labelTruncateAt).
onValueChange(value: BarChartEventProps) => voidCallback when a bar or legend item is clicked. Returns { eventType: "bar" | "category", categoryClicked, ...dataRow } or null on deselect.
classNamestringAdditional CSS classes applied to the outer wrapper div. Default height is h-80.