GitHub
Core
Glass
Brutal
Humanist

Bar Chart
Pro

A chart that displays data using rectangular bars to compare values across categories.

Bar Chart Playground

Bar Chart Playground
Preview
Code
Revenue
Expenses
Profit
Controls
Mode:
Shared
Focused
Series:
1
2
3
Grid:
Tooltip:
Legend:

Stacked Bar Chart Playground

Stacked Bar Chart Playground
Preview
Code
Series 1
Series 2
Series 3
Series 4
Controls
Series:
2
3
4
Grid:
Tooltip:
Legend:

Installation

You can add the bar chart component to your project manually:

1

Install the following dependencies:

npm install class-variance-authority clsx tailwind-merge recharts
2

Copy and paste the following code into your project.

Loading...
3

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>
AspectSharedFocused
Hover scopeEntire bar groupIndividual bar only
Bar color changeAll bars in group → mediumOnly hovered bar → medium
Active dotHiddenShown at top-center
Tooltip arrowHiddenShown (downward)
Tooltip positionFollows cursorAnchored 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 descriptive aria-label
  • Keyboard navigation: Legend items are focusable and toggleable with Enter/Space
  • Reduced motion: Animations disabled when prefers-reduced-motion: reduce is set
  • Tooltips: Announced via role="tooltip" with proper ARIA semantics

ChartContainer Props

PropTypeDefaultDescription
size'large' | 'medium''large'Chart size variant controlling radius and padding.
loadingbooleanfalseShow skeleton loading state.
emptybooleanfalseShow empty data placeholder.
aria-labelstring'Chart'Accessible label for the chart.
minHeightnumber300Minimum chart height in pixels.
aspectRationumberWidth/height aspect ratio.
classNamestring''Additional CSS classes.

VersaBarChart Props

PropTypeDefaultDescription
dataChartDataPoint[]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.
legendbooleantrueShow auto-generated legend.
legendSize'default' | 'small'autoLegend size. Auto-derived from chart size.
legendMarkerStyle'circle' | 'horizontal-line' | 'vertical-line''circle'Legend indicator shape.
classNamestring''Additional CSS classes.

ChartBar Props

PropTypeDefaultDescription
dataKeystringRequired. Key in data for this bar series.
color'primary' | 'secondary' | 'tertiary' | 'quaternary'autoBrand color token. Auto-assigned from palette.
namestringdataKeyHuman-readable name for legend/tooltip.
radiusnumbertokenCorner radius. Defaults to --corner-radius-default-small token.
showActiveDotbooleantrueShow active indicator dot on hover.
classNamestring''Additional CSS classes.

ChartXAxis Props

PropTypeDefaultDescription
dataKeystringRequired. Key in data for x-axis labels.
maxLabelLengthnumber8Truncation length for tick labels.
formatter(value) => stringCustom tick label formatter.
hidebooleanfalseHide the axis.

ChartYAxis Props

PropTypeDefaultDescription
formatter(value) => stringCustom tick value formatter.
widthnumber40Axis width in pixels.
hidebooleanfalseHide the axis.

ChartTooltip Props

PropTypeDefaultDescription
contentReact.ComponentTypeCustom tooltip renderer component.
formatter(value, name) => stringValue formatter for default tooltip.
labelFormatter(label) => stringLabel/header formatter for default tooltip.
classNamestring''Additional CSS classes.

ChartGrid Props

PropTypeDefaultDescription
horizontalbooleantrueShow horizontal grid lines.
verticalbooleanfalseShow vertical grid lines.

ChartLegend Props

PropTypeDefaultDescription
size'default' | 'small''default'Legend size variant.
markerStyle'circle' | 'horizontal-line' | 'vertical-line''circle'Indicator shape.
showValuebooleanfalseShow value next to each series.
seriesChartSeries[][]Series definitions for rendering.
onToggle(dataKey: string) => voidCallback when a series is toggled.
hiddenSeriesSet<string>new Set()Set of hidden series data keys.

On this page