Stacked Bar Chart with Horizontal Line
This example shows a stacked bar chart with a horizontal line indicating a threshold.
The chart uses the Bar component to create the bars, and the ReferenceLinecomponent to create the horizontal line.
The LabelList component is used to display the total value of the bars above the threshold.
import {
BarChart,
Bar,
XAxis,
YAxis,
CartesianGrid,
Tooltip,
Legend,
ReferenceLine,
LabelList,
LabelProps,
} from 'recharts';
import { RechartsDevtools } from '@recharts/devtools';
// #region Sample data
const data = [
{
name: 'Page A',
data1: 4000,
data2: 2400,
data3: 1500,
amt: 2400,
},
{
name: 'Page B',
data1: 9000,
data2: 1398,
data3: 2500,
amt: 2210,
},
{
name: 'Page C',
data1: 2000,
data2: 9800,
data3: 4200,
amt: 2290,
},
{
name: 'Page D',
data1: 2780,
data2: 3908,
data3: 1300,
amt: 2000,
},
{
name: 'Page E',
data1: 1890,
data2: 4800,
data3: 5400,
amt: 2181,
},
{
name: 'Page F',
data1: 2390,
data2: 8800,
data3: 1500,
amt: 3000,
},
{
name: 'Page G',
data1: 3490,
data2: 4300,
data3: 2600,
amt: 2100,
},
];
// #endregion
const THRESHOLD = 18000;
type DataPoint = (typeof data)[number];
const StackTotalLabel = (props: LabelProps) => {
const { x, y, width, value } = props;
const total = Number(value);
if (x == null || y == null || width == null || Number.isNaN(total)) {
return null;
}
const label = total.toLocaleString();
const cx = Number(x) + Number(width) / 2;
const cy = Number(y) - 18;
const boxWidth = label.length * 8 + 16;
const boxHeight = 22;
const borderRadius = 6;
return (
<g>
<rect
x={cx - boxWidth / 2}
y={cy - boxHeight / 2}
width={boxWidth}
height={boxHeight}
rx={borderRadius}
ry={borderRadius}
fill="#fff"
stroke="#E2F0CB"
strokeWidth={1.5}
/>
<text x={cx} y={cy} fill="#333" textAnchor="middle" dominantBaseline="middle" fontSize={12} fontWeight={400}>
{label}
</text>
</g>
);
};
const StackedBarChartWithHorizontalLine = () => {
return (
<BarChart
style={{ width: '100%', maxWidth: '700px', maxHeight: '70vh', aspectRatio: 1.618 }}
responsive
data={data}
margin={{
top: 40,
right: 0,
left: 30,
bottom: 5,
}}
>
<CartesianGrid />
<XAxis dataKey="name" niceTicks="snap125" />
<YAxis width="auto" niceTicks="snap125" />
<Tooltip cursor={false} />
<Legend />
<ReferenceLine
y={THRESHOLD}
stroke="red"
strokeWidth={2}
label={{ value: 'Threshold', fill: 'red', position: 'left' }}
/>
<Bar dataKey="data1" stackId="a" />
<Bar dataKey="data2" stackId="a" />
<Bar dataKey="data3" stackId="a">
<LabelList
content={StackTotalLabel}
position="top"
offset={8}
valueAccessor={entry => {
const point = entry.payload as DataPoint;
return point.data1 + point.data2 + point.data3;
}}
/>
</Bar>
<RechartsDevtools />
</BarChart>
);
};
export default StackedBarChartWithHorizontalLine;