'use client'; import { Bar, BarChart as RBarChart, CartesianGrid, ResponsiveContainer, Tooltip, XAxis, YAxis } from 'recharts'; import ChartCard, { ChartTooltip } from './ChartCard'; import { axisProps, seriesColor, type ChartSeries } from './chartSeries'; import { compactNumber, useChartPalette } from './chartTheme'; /** * Bars for comparing magnitude across categories — grouped, stacked, or * horizontal for long names. * * ── Which arrangement ─────────────────────────────────────────────────────── * * grouped the series side by side: compare series WITHIN a category * stacked one bar per category, split by series: the total is the story, * the parts are its make-up (part-to-whole) * horizontal for many categories or long names, which a column chart * would have to rotate or truncate * * Bars are capped at 24px and never fill the band — the leftover is air. * Data-ends are 4px rounded and square at the baseline; a stack rounds only * its top segment, and a 2px gap in the card's own colour separates touching * segments instead of a drawn border. */ export default function BarChart({ title, hint, data, x, series, stacked = false, horizontal = false, format = compactNumber, height = 280, className, }: { title: string; hint?: string; data: Record[]; /** The category key. */ x: string; series: ChartSeries[]; stacked?: boolean; /** Bars left-to-right instead of columns bottom-up. */ horizontal?: boolean; format?: (v: number) => string; height?: number; className?: string; }) { const p = useChartPalette(); const axis = axisProps(p); const last = series.length - 1; return ( ({ label: s.label, color: seriesColor(p, s, i) }))} table={{ columns: [{ key: x, label: x.charAt(0).toUpperCase() + x.slice(1) }, ...series.map((s) => ({ key: s.key, label: s.label, align: 'right' as const, format: (v: unknown) => format(Number(v)) }))], rows: data, }} >
{horizontal ? ( <> ) : ( <> )} } /> {series.map((s, i) => { // Only the outermost segment of a stack gets the rounded end. const rounded = !stacked || i === last; const r = rounded ? 4 : 0; return ( ); })}
); }