Skip to content

shadcn.io is an independent project built on shadcn/ui

Free

A stacked bar chart with a legend for Ark UI

One bar per month, desktop on the baseline and mobile on top, rounded only on the outer ends, with a legend.

One bar per month. Desktop sits on the baseline and mobile sits on top, so the height is the total. Only the outer ends are rounded. A legend names both series.

Use it when the month's total and its split should be visible at once. Side-by-side bars are better for comparing the two series, and a Table is better for the figures. In React, Ark UI does not stack the bars. You give both series the same stack.

Preview

Preview width

Installation

Sign in to get your install command
Free with an account. It carries your token, so the CLI installs everything in one go.
Use email insteadNo credit card

Anatomy

Chart anatomy: container, grid, axis, bar, tooltip, legend

Usage

<div className="w-full max-w-xl rounded-md border bg-background p-4">
  <ChartContainer config={chartConfig}>
    <BarChart accessibilityLayer data={chartData}>
      <CartesianGrid vertical={false} />
      <XAxis
        axisLine={false}
        dataKey="month"
        tickFormatter={formatMonth}
        tickLine={false}
        tickMargin={10}
      />
      <ChartTooltip content={renderTooltipContent} />
      <ChartLegend content={<ChartLegendContent />} />
      <Bar
        dataKey="desktop"
        fill="var(--color-desktop)"
        radius={[0, 0, 4, 4]}
        stackId="a"
      />
      <Bar
        dataKey="mobile"
        fill="var(--color-mobile)"
        radius={[4, 4, 0, 0]}
        stackId="a"
      />
    </BarChart>
  </ChartContainer>
</div>

FAQ

How do the bars stack?

Both Bar components set stackId="a". Desktop is first, so it sits on the baseline. Mobile is second, so it sits on top. The top of the mobile segment is that month's total. Each chartData row has desktop and mobile.

Why are the rounded corners split across the two bars?

Desktop sets radius={[0, 0, 4, 4]}, the bottom two corners. Mobile sets radius={[4, 4, 0, 0]}, the top two corners. The corners that meet in the middle stay square. Fills are var(--color-desktop) and var(--color-mobile).

How does the legend get its labels?

ChartLegend sets content to ChartLegendContent, which lists Desktop and Mobile from config, each with a color swatch. This file passes no onClick. verticalAlign stays at the default, bottom, which adds space above the legend.

What does the tooltip show?

ChartTooltipContent sets hideLabel, so the month isn't repeated in the title. The rows are Desktop and Mobile with their values. This ChartTooltip doesn't set cursor={false}, so the hovered bar keeps the default cursor.

How are the month ticks shortened?

XAxis uses dataKey="month" and tickFormatter={formatMonth}, which keeps value.slice(0, 3). axisLine and tickLine are false, and tickMargin is 10. CartesianGrid sets vertical={false}.

Can I move across the bars with the keyboard?

Yes. BarChart sets accessibilityLayer, so the bars can take focus. The month tick and the labels in config name each stack. ChartContainer keeps the default 16:9 box inside a w-full max-w-xl frame.

API Reference

Chart

Sets config={chartConfig} and content={renderTooltipContent}. The rest is on the Chart page.