Bar Chart

A composable bar chart with spring animations, stacked bars, horizontal orientation, and grouped series support

Preview

Installation

pnpm dlx shadcn@latest add https://ui.bklit.com/r/bar-chart.json

Usage

The Bar Chart uses the same composable API as the Line and Area charts. Build charts by combining components:

import {
  BarChart,
  Bar,
  BarXAxis,
  Grid,
  ChartTooltip,
} from "@bklitui/ui/charts";

const data = [
  { month: "Jan", revenue: 12000, profit: 4500 },
  { month: "Feb", revenue: 15500, profit: 5200 },
  // ... more data
];

export default function RevenueChart() {
  return (
    <BarChart data={data} xDataKey="month">
      <Grid horizontal />
      <Bar dataKey="revenue" fill="var(--chart-line-primary)" lineCap="round" />
      <Bar
        dataKey="profit"
        fill="var(--chart-line-secondary)"
        lineCap="round"
      />
      <BarXAxis />
      <ChartTooltip />
    </BarChart>
  );
}

Stacked Bars

Use the stacked prop to stack bars on top of each other. Add stackGap to create visual separation between segments, allowing each bar to have its own rounded corners.

<BarChart data={data} xDataKey="month" stacked stackGap={3}><Grid horizontal /><Bar dataKey="desktop" fill="hsl(217, 91%, 60%)" lineCap={4} stackGap={3} /><Bar dataKey="mobile" fill="hsl(217, 91%, 75%)" lineCap={4} stackGap={3} /><BarXAxis /><ChartTooltip /></BarChart>

Horizontal Bars

Use orientation="horizontal" to create horizontal bar charts with categories on the Y-axis.

<BarChart data={data} xDataKey="browser" orientation="horizontal" margin={{ left: 80 }}><Grid horizontal={false} vertical fadeVertical /><Bar dataKey="users" fill="hsl(217, 91%, 60%)" lineCap={4} /><BarYAxis /><ChartTooltip showCrosshair={false} /></BarChart>

90 Days of Data

A single series bar chart showing 90 days of data with square caps.

<BarChart data={dailyData} xDataKey="day" barGap={0.1}><Grid horizontal /><Bar dataKey="value" lineCap="butt" /><BarXAxis maxLabels={8} /><ChartTooltip /></BarChart>

Gradients and Patterns

Use visx gradient and pattern components to create custom bar fills. Place them as children of BarChart and reference them by ID.

Gradient Fill

Use the stroke prop to set the tooltip dot color when using gradient fills.

import { LinearGradient } from "@bklitui/ui/charts";<BarChart data={data} xDataKey="month"><LinearGradient id="barGradient" from="hsl(217, 91%, 60%)" to="hsl(280, 87%, 65%)" /><Grid horizontal /><Bar dataKey="revenue" fill="url(#barGradient)" stroke="hsl(217, 91%, 60%)" lineCap={4} /><BarXAxis /><ChartTooltip /></BarChart>

Pattern Fill

Use the stroke prop to set a solid tooltip dot color when using pattern fills.

import { PatternLines } from "@bklitui/ui/charts";<BarChart data={data} xDataKey="month"><PatternLines  id="barPattern"  height={8}  width={8}  stroke="hsl(217, 91%, 60%)"  strokeWidth={2}  orientation={["diagonal"]}/><Grid horizontal /><Bar dataKey="revenue" fill="url(#barPattern)" stroke="hsl(217, 91%, 60%)" lineCap={4} /><BarXAxis /><ChartTooltip /></BarChart>

Available Fills

Gradients (from @visx/gradient):

  • LinearGradient - Custom linear gradient with from, to, and optional fromOpacity/toOpacity
  • RadialGradient - Radial gradient with from, to, and r (radius)
  • Pre-built: GradientDarkgreenGreen, GradientOrangeRed, GradientPinkBlue, GradientPurpleTeal, GradientTealBlue, etc.

Patterns (from @visx/pattern):

  • PatternLines - Diagonal, horizontal, or vertical lines
  • PatternCircles - Dot pattern
  • PatternHexagons - Hexagonal pattern
  • PatternWaves - Wave pattern

Components

BarChart

The root component that provides context to all children.

PropTypeDefaultDescription
dataRecord<string, unknown>[]requiredArray of data points
xDataKeystring"name"Key in data for categorical axis values
marginPartial<Margin>{ top: 40, right: 40, bottom: 40, left: 40 }Chart margins
animationDurationnumber1100Animation duration in ms
aspectRatiostring"2 / 1"CSS aspect ratio
barGapnumber0.2Gap between bar groups (0-1 fraction of band width)
barWidthnumber-Fixed bar width in pixels (auto-sizes if not set)
orientation"vertical" | "horizontal""vertical"Bar chart orientation
stackedbooleanfalseStack bars instead of grouping them
stackGapnumber0Gap between stacked bar segments in pixels
classNamestring""Additional CSS class

Bar

Renders a bar for each data point with configurable styling and animations.

PropTypeDefaultDescription
dataKeystringrequiredKey in data for values
fillstringvar(--chart-line-primary)Bar fill color (can be gradient/pattern url)
strokestring-Tooltip dot color. Use when fill is a gradient/pattern
lineCap"round" | "butt" | number"round"Bar end cap style or custom radius
animatebooleantrueEnable animation
animationType"grow" | "fade""grow"Animation style
fadedOpacitynumber0.3Opacity when another bar is hovered
staggerDelaynumberautoDelay between bars (auto-calculated based on bar count)
stackGapnumber0Gap between stacked bars in pixels

BarXAxis

Displays categorical labels along the x-axis (for vertical bar charts).

PropTypeDefaultDescription
tickerHalfWidthnumber50Width of ticker for fade calculation
showAllLabelsbooleanfalseShow all labels (may crowd)
maxLabelsnumber12Maximum labels to show

BarYAxis

Displays categorical labels along the y-axis (for horizontal bar charts).

PropTypeDefaultDescription
showAllLabelsbooleantrueShow all labels
maxLabelsnumber20Maximum labels to show

Grid

The Grid component now supports fadeVertical for vertical grid lines.

PropTypeDefaultDescription
horizontalbooleantrueShow horizontal grid lines
verticalbooleanfalseShow vertical grid lines
fadeHorizontalbooleantrueFade horizontal lines at left/right edges
fadeVerticalbooleanfalseFade vertical lines at top/bottom edges

Animation

Bars animate with the same easing as Line charts (cubic-bezier(0.85, 0, 0.15, 1)) for a smooth, organic feel. The stagger delay is automatically calculated based on the number of bars to ensure all animations complete within the total animation duration (~1.2s).

Grow Animation (Default)

Bars grow from zero to their final size:

<Bar dataKey="revenue" animationType="grow" />

Fade Animation

Bars fade in with a blur effect:

<Bar dataKey="revenue" animationType="fade" />

Custom Stagger

Stagger is calculated automatically, but you can override it:

// Override automatic stagger with custom delay
<Bar dataKey="revenue" staggerDelay={0.02} />

// No stagger (all bars animate together)
<Bar dataKey="revenue" staggerDelay={0} />

Line Cap Styles

Control the bar end style:

// Rounded caps (default) - full rounding
<Bar dataKey="revenue" lineCap="round" />

// Square caps - no rounding
<Bar dataKey="revenue" lineCap="butt" />

// Custom radius in pixels
<Bar dataKey="revenue" lineCap={4} />
<Bar dataKey="revenue" lineCap={8} />

Examples

Stacked with Legend

Desktop
Mobile
const legendItems = [{ label: "Desktop", value: 0, color: "hsl(217, 91%, 60%)" },{ label: "Mobile", value: 0, color: "hsl(217, 91%, 75%)" },];<div><BarChart data={data} xDataKey="month" stacked stackGap={3}>  <Grid horizontal />  <Bar dataKey="desktop" fill="hsl(217, 91%, 60%)" lineCap={4} stackGap={3} />  <Bar dataKey="mobile" fill="hsl(217, 91%, 75%)" lineCap={4} stackGap={3} />  <BarXAxis />  <ChartTooltip /></BarChart><Legend items={legendItems} className="flex-row justify-center gap-6">  <LegendItem className="flex items-center gap-2">    <LegendMarker />    <LegendLabel />  </LegendItem></Legend></div>

Narrow Gaps

<BarChart data={data} xDataKey="month" barGap={0.1}><Grid horizontal /><Bar dataKey="revenue" fill="var(--chart-line-primary)" lineCap="round" /><BarXAxis /><ChartTooltip /></BarChart>

Custom Tooltip

<BarChart data={data} xDataKey="month"><Grid horizontal /><Bar dataKey="revenue" fill="var(--chart-line-primary)" lineCap="round" /><BarXAxis /><ChartTooltip  rows={(point) => [    {      color: "var(--chart-line-primary)",      label: "Revenue",      value: `$${point.revenue?.toLocaleString()}`,    },  ]}/></BarChart>

No Gap with Custom Line Indicator

A bar chart with zero gap between bars, gradient fill, and a custom horizontal line indicator. Each bar has its own line that rises from the bottom on hover.

// Each bar gets an animated line that rises on hoverfunction AnimatedBarLine({ barX, barTopY, barBottomY, width, isHovered }) {const animatedY = useSpring(barBottomY, { stiffness: 300, damping: 30 });useEffect(() => {  animatedY.set(isHovered ? barTopY : barBottomY);}, [isHovered, barTopY, barBottomY]);return (  <motion.rect    x={barX}    width={width}    height={2}    fill="white"    style={{ opacity: isHovered ? 1 : 0, y: animatedY }}  />);}// Renders a line indicator for each barfunction BarLineIndicators({ data }) {const { barScale, bandWidth, innerHeight, yScale, hoveredBarIndex } = useChart();return data.map((d, i) => (  <AnimatedBarLine    key={d.month}    barX={barScale(d.month)}    barTopY={yScale(d.revenue)}    barBottomY={innerHeight}    width={bandWidth}    isHovered={hoveredBarIndex === i}  />));}<BarChart data={data} xDataKey="month" barGap={0}><LinearGradient id="gradient" from="var(--chart-3)" to="transparent" /><Grid horizontal /><Bar dataKey="revenue" fill="url(#gradient)" lineCap="butt" stroke="var(--chart-3)" /><BarXAxis /><ChartTooltip showCrosshair={false} showDots={false} /><BarLineIndicators data={data} /></BarChart>

Theming

The Bar Chart uses the same CSS variables as other charts:

:root {
  --chart-background: oklch(1 0 0);
  --chart-foreground: oklch(0.145 0.004 285);
  --chart-foreground-muted: oklch(0.55 0.014 260);
  --chart-line-primary: oklch(0.623 0.214 255);
  --chart-line-secondary: oklch(0.705 0.015 265);
  --chart-crosshair: oklch(0.4 0.1828 274.34);
  --chart-grid: oklch(0.9 0 0);
}

.dark {
  --chart-background: oklch(0.145 0 0);
  --chart-foreground: oklch(0.45 0 0);
  --chart-crosshair: oklch(0.45 0 0);
  --chart-grid: oklch(0.25 0 0);
}

Dependencies

This component requires the same packages as the other charts:

pnpm add @visx/shape @visx/scale @visx/responsive @visx/event @visx/grid d3-array motion react-use-measure