Bar ChartPro
A chart that displays data using rectangular bars to compare values across categories.
Bar Chart Playground
Stacked Bar Chart Playground
Installation
You can add the bar chart component to your project manually:
Install the following dependencies:
npm install class-variance-authority clsx tailwind-merge rechartsCopy and paste the following code into your project.
Update the import paths to match your project setup.
Update the import aliases (e.g. @/components, @/utils) in the copied files to match your project's path configuration.
Basic Usage
A simple single-series bar chart:
import {
ChartContainer,
VersaBarChart,
ChartBar,
ChartGrid,
ChartXAxis,
ChartYAxis,
ChartTooltip,
} from '@versaui/ui/components/Charts';
const data = [
{ month: 'Jan', revenue: 4200 },
{ month: 'Feb', revenue: 5800 },
{ month: 'Mar', revenue: 4900 },
{ month: 'Apr', revenue: 7200 },
{ month: 'May', revenue: 6100 },
{ month: 'Jun', revenue: 8400 },
];
<ChartContainer size="large" aria-label="Monthly revenue">
<VersaBarChart data={data}>
<ChartGrid horizontal />
<ChartXAxis dataKey="month" />
<ChartYAxis />
<ChartTooltip />
<ChartBar dataKey="revenue" color="primary" name="Revenue" />
</VersaBarChart>
</ChartContainer>Interaction Modes
Bar charts support two interaction modes that control hover behavior, tooltip positioning, and active indicators:
Shared Mode (Default)
Entire bar group responds to hover — optimized for multi-series and dense datasets:
<ChartContainer size="large" aria-label="Revenue">
<VersaBarChart data={data} interactionMode="shared">
<ChartGrid horizontal />
<ChartXAxis dataKey="month" />
<ChartYAxis />
<ChartTooltip />
<ChartBar dataKey="revenue" color="primary" name="Revenue" />
<ChartBar dataKey="expenses" color="secondary" name="Expenses" />
</VersaBarChart>
</ChartContainer>Focused Mode
Only the directly hovered bar activates — designed for premium analytics experiences:
<ChartContainer size="large" aria-label="Revenue">
<VersaBarChart data={data} interactionMode="focused">
<ChartGrid horizontal />
<ChartXAxis dataKey="month" />
<ChartYAxis />
<ChartTooltip />
<ChartBar dataKey="revenue" color="primary" name="Revenue" />
<ChartBar dataKey="expenses" color="secondary" name="Expenses" />
</VersaBarChart>
</ChartContainer>| Aspect | Shared | Focused |
|---|---|---|
| Hover scope | Entire bar group | Individual bar only |
| Bar color change | All bars in group → medium | Only hovered bar → medium |
| Active dot | Hidden | Shown at top-center |
| Tooltip arrow | Hidden | Shown (downward) |
| Tooltip position | Follows cursor | Anchored above bar |
Multi-Series
Add multiple <ChartBar> children for grouped bar charts. Legend is auto-generated:
<ChartContainer size="large" aria-label="Financial overview">
<VersaBarChart data={data}>
<ChartGrid horizontal />
<ChartXAxis dataKey="month" />
<ChartYAxis />
<ChartTooltip />
<ChartBar dataKey="revenue" color="primary" name="Revenue" />
<ChartBar dataKey="expenses" color="secondary" name="Expenses" />
<ChartBar dataKey="profit" color="tertiary" name="Profit" />
</VersaBarChart>
</ChartContainer>Stacked Bar Chart
Add stackId to <ChartBar> children to stack bars vertically. Corner radius is automatically applied per stack position — top segment gets top corners, bottom segment gets bottom corners, middle segments have no rounding:
const data = [
{ month: 'Jan', series1: 30, series2: 22, series3: 18, series4: 10 },
{ month: 'Feb', series1: 45, series2: 30, series3: 12, series4: 12 },
// ...
];
<ChartContainer size="large" aria-label="Stacked bar chart">
<VersaBarChart data={data}>
<ChartGrid horizontal />
<ChartXAxis dataKey="month" />
<ChartYAxis />
<ChartTooltip />
<ChartBar dataKey="series1" color="primary" name="Series 1" stackId="a" />
<ChartBar dataKey="series2" color="secondary" name="Series 2" stackId="a" />
<ChartBar dataKey="series3" color="tertiary" name="Series 3" stackId="a" />
<ChartBar dataKey="series4" color="quaternary" name="Series 4" stackId="a" />
</VersaBarChart>
</ChartContainer>Chart Size
Two size variants match the Figma spec — large and medium:
{/* Large (default) — 16px corner-radius, generous padding */}
<ChartContainer size="large">
<VersaBarChart data={data} size="large">...</VersaBarChart>
</ChartContainer>
{/* Medium — 12px corner-radius, tighter padding */}
<ChartContainer size="medium">
<VersaBarChart data={data} size="medium">...</VersaBarChart>
</ChartContainer>Custom Tooltip
Override the tooltip content with a custom renderer:
import type { ChartTooltipPayload } from '@versaui/ui/components/Charts';
function CustomTooltip({ active, payload, label }: ChartTooltipPayload) {
if (!active || !payload?.length) return null;
return (
<div className="bg-white p-3 rounded shadow-lg border">
<p className="font-semibold">{label}</p>
{payload.map((entry) => (
<p key={entry.dataKey}>{entry.name}: ${entry.value.toLocaleString()}</p>
))}
</div>
);
}
<ChartTooltip content={CustomTooltip} />Value Formatting
Format axis ticks and tooltip values:
<ChartYAxis formatter={(value) => `$${(value / 1000).toFixed(0)}k`} />
<ChartTooltip formatter={(value, name) => `$${value.toLocaleString()}`} />Grid Lines
Control horizontal and vertical grid lines:
{/* Horizontal only (default) */}
<ChartGrid horizontal />
{/* Both directions */}
<ChartGrid horizontal vertical />
{/* No grid */}
{/* Simply omit <ChartGrid /> */}Legend Configuration
The legend is auto-generated from <ChartBar> children. Customize it:
{/* Hide legend */}
<VersaBarChart data={data} legend={false}>...</VersaBarChart>
{/* Custom legend size and marker style */}
<VersaBarChart
data={data}
legendSize="small"
legendMarkerStyle="horizontal-line"
>
...
</VersaBarChart>Loading & Empty States
Built-in skeleton loading and empty data states:
{/* Loading state — shows animated skeleton bars */}
<ChartContainer size="large" loading>
<VersaBarChart data={[]}>...</VersaBarChart>
</ChartContainer>
{/* Empty state — shows "No data available" message */}
<ChartContainer size="large" empty>
<VersaBarChart data={[]}>...</VersaBarChart>
</ChartContainer>Accessibility
The Bar Chart components are fully accessible:
- Screen readers: Chart container uses
role="img"with descriptivearia-label - Keyboard navigation: Legend items are focusable and toggleable with
Enter/Space - Reduced motion: Animations disabled when
prefers-reduced-motion: reduceis set - Tooltips: Announced via
role="tooltip"with proper ARIA semantics
ChartContainer Props
| Prop | Type | Default | Description |
|---|---|---|---|
size | 'large' | 'medium' | 'large' | Chart size variant controlling radius and padding. |
loading | boolean | false | Show skeleton loading state. |
empty | boolean | false | Show empty data placeholder. |
aria-label | string | 'Chart' | Accessible label for the chart. |
minHeight | number | 300 | Minimum chart height in pixels. |
aspectRatio | number | — | Width/height aspect ratio. |
className | string | '' | Additional CSS classes. |
VersaBarChart Props
| Prop | Type | Default | Description |
|---|---|---|---|
data | ChartDataPoint[] | — | Required. Array of data objects. |
size | 'large' | 'medium' | 'large' | Chart size variant. |
interactionMode | 'shared' | 'focused' | 'shared' | Hover interaction behavior. Shared highlights entire group; Focused highlights individual bar with active dot and anchored tooltip. |
legend | boolean | true | Show auto-generated legend. |
legendSize | 'default' | 'small' | auto | Legend size. Auto-derived from chart size. |
legendMarkerStyle | 'circle' | 'horizontal-line' | 'vertical-line' | 'circle' | Legend indicator shape. |
className | string | '' | Additional CSS classes. |
ChartBar Props
| Prop | Type | Default | Description |
|---|---|---|---|
dataKey | string | — | Required. Key in data for this bar series. |
color | 'primary' | 'secondary' | 'tertiary' | 'quaternary' | auto | Brand color token. Auto-assigned from palette. |
name | string | dataKey | Human-readable name for legend/tooltip. |
radius | number | token | Corner radius. Defaults to --corner-radius-default-small token. |
showActiveDot | boolean | true | Show active indicator dot on hover. |
className | string | '' | Additional CSS classes. |
ChartXAxis Props
| Prop | Type | Default | Description |
|---|---|---|---|
dataKey | string | — | Required. Key in data for x-axis labels. |
maxLabelLength | number | 8 | Truncation length for tick labels. |
formatter | (value) => string | — | Custom tick label formatter. |
hide | boolean | false | Hide the axis. |
ChartYAxis Props
| Prop | Type | Default | Description |
|---|---|---|---|
formatter | (value) => string | — | Custom tick value formatter. |
width | number | 40 | Axis width in pixels. |
hide | boolean | false | Hide the axis. |
ChartTooltip Props
| Prop | Type | Default | Description |
|---|---|---|---|
content | React.ComponentType | — | Custom tooltip renderer component. |
formatter | (value, name) => string | — | Value formatter for default tooltip. |
labelFormatter | (label) => string | — | Label/header formatter for default tooltip. |
className | string | '' | Additional CSS classes. |
ChartGrid Props
| Prop | Type | Default | Description |
|---|---|---|---|
horizontal | boolean | true | Show horizontal grid lines. |
vertical | boolean | false | Show vertical grid lines. |
ChartLegend Props
| Prop | Type | Default | Description |
|---|---|---|---|
size | 'default' | 'small' | 'default' | Legend size variant. |
markerStyle | 'circle' | 'horizontal-line' | 'vertical-line' | 'circle' | Indicator shape. |
showValue | boolean | false | Show value next to each series. |
series | ChartSeries[] | [] | Series definitions for rendering. |
onToggle | (dataKey: string) => void | — | Callback when a series is toggled. |
hiddenSeries | Set<string> | new Set() | Set of hidden series data keys. |