shadcn.io is an independent project built on shadcn/ui
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.
Installation
Anatomy

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.
API Reference
Chart
Sets config={chartConfig} and content={renderTooltipContent}. The rest is on the Chart page.





