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
| Prop | Type | Default | Description |
|---|---|---|---|
| data* | Record<string, any>[] | — | Array of data objects. Each object should have the index key and one key per category. |
| index* | string | — | The 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. |
| colors | ChartColor[] | CHART_COLORS | Color palette for each category. Cycles if fewer colors than categories. |
| valueFormatter | (value: number) => string | v => 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%. |
| barCategoryGap | string | number | — | Gap between bar groups. Accepts a percentage string (e.g. "20%") or pixel value. |
| showXAxis | boolean | true | Show or hide the X-axis. |
| showYAxis | boolean | true | Show or hide the Y-axis. |
| showGridLines | boolean | true | Show or hide background grid lines. |
| yAxisWidth | number | — | Width in pixels reserved for the Y-axis. Auto-inferred from data if omitted. |
| xAxisLabel | string | — | Optional label rendered below the X-axis. |
| yAxisLabel | string | — | Optional label rendered to the left of the Y-axis, rotated 90°. |
| axisTextSize | "xs" | "sm" | "md" | "lg" | number | "xs" | Font size for axis tick labels. |
| autoScaleLabels | boolean | false | Automatically shrinks axis tick font size as entry count grows, preventing label overlap on large datasets without needing scroll. |
| tickGap | number | 5 | Minimum gap in pixels between X-axis ticks. |
| startEndOnly | boolean | false | Only show the first and last tick labels on the category axis. |
| intervalType | "preserveStartEnd" | "equidistantPreserveStart" | "equidistantPreserveStart" | Recharts tick interval strategy for the category axis. |
| allowDecimals | boolean | true | Allow decimal values on the numeric axis. |
| autoMinValue | boolean | false | Use "auto" for the numeric axis minimum instead of 0. |
| minValue | number | — | Explicit minimum for the numeric axis. |
| maxValue | number | — | Explicit maximum for the numeric axis. |
| showLegend | boolean | true | Show or hide the legend. |
| legendPosition | "left" | "center" | "right" | "right" | Horizontal alignment of the legend. |
| enableLegendSlider | boolean | false | Makes the legend horizontally scrollable with arrow buttons when items overflow. |
| legendTextSize | "xs" | "sm" | "md" | "lg" | number | "xs" | Font size for legend labels. |
| showTooltip | boolean | true | Show or hide the tooltip on hover. |
| tooltipCallback | (content: TooltipProps) => void | — | Callback fired whenever the tooltip active state or label changes. |
| customTooltip | React.ComponentType<TooltipProps> | — | Custom tooltip component. Receives active, payload, and label props. |
| rounded | boolean | false | Apply rounded corners to bars. |
| labelTruncateAt | number | — | Truncate axis labels at this many characters, appending "...". When omitted, labels are shown in full. |
| minBarSize | number | — | Minimum pixels per bar row in vertical layout. When set, chart height is computed as data.length × minBarSize. Has no effect in horizontal layout. |
| maxHeight | number | string | — | Caps the outer container height and enables vertical scrolling when the computed height (from minBarSize) exceeds this value. |
| tooltipFullLabel | boolean | true | When true the tooltip shows the full label text. Set to false to show the truncated label (requires labelTruncateAt). |
| onValueChange | (value: BarChartEventProps) => void | — | Callback when a bar or legend item is clicked. Returns { eventType: "bar" | "category", categoryClicked, ...dataRow } or null on deselect. |
| className | string | — | Additional CSS classes applied to the outer wrapper div. Default height is h-80. |