Make pie chart responsive and reduce label text size
All checks were successful
Build and Push Docker Images / docker (push) Successful in 59s

- Reduce label font sizes: 10px name, 9px details (was 14px/12px)
- Add print-friendly smaller sizes: 7px/6px
- Make container fully responsive with max-width constraints
- Reduce label extension distance from ±50px to ±30px
- Reduce label radius from outerRadius+60 to outerRadius+35
- Use fixed pie dimensions (80/50) instead of calculated sizes
- Reduce connector line width from 2px to 1.5px
- Add print-specific max-width and height constraints

Fixes text overflow and makes chart fit properly on page while
maintaining readability and print quality.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Matt 2025-10-31 17:57:32 +01:00
parent ec0c8a2fbc
commit 4dfc420535

View File

@ -50,13 +50,13 @@ export function RechartsPortfolioPieChart({
} = props; } = props;
const RADIAN = Math.PI / 180; const RADIAN = Math.PI / 180;
const radius = outerRadius + 60; const radius = outerRadius + 35;
const x = cx + radius * Math.cos(-midAngle * RADIAN); const x = cx + radius * Math.cos(-midAngle * RADIAN);
const y = cy + radius * Math.sin(-midAngle * RADIAN); const y = cy + radius * Math.sin(-midAngle * RADIAN);
const textAnchor = x > cx ? 'start' : 'end'; const textAnchor = x > cx ? 'start' : 'end';
// Calculate line endpoint for label connector // Calculate line endpoint for label connector
const lineEndX = x > cx ? x + 50 : x - 50; const lineEndX = x > cx ? x + 30 : x - 30;
const labelStartX = cx + (outerRadius + 10) * Math.cos(-midAngle * RADIAN); const labelStartX = cx + (outerRadius + 10) * Math.cos(-midAngle * RADIAN);
const labelStartY = cy + (outerRadius + 10) * Math.sin(-midAngle * RADIAN); const labelStartY = cy + (outerRadius + 10) * Math.sin(-midAngle * RADIAN);
@ -69,7 +69,7 @@ export function RechartsPortfolioPieChart({
x2={x} x2={x}
y2={y} y2={y}
stroke={fill} stroke={fill}
strokeWidth="2" strokeWidth="1.5"
className="print:stroke-gray-400" className="print:stroke-gray-400"
/> />
<line <line
@ -78,35 +78,35 @@ export function RechartsPortfolioPieChart({
x2={lineEndX} x2={lineEndX}
y2={y} y2={y}
stroke={fill} stroke={fill}
strokeWidth="2" strokeWidth="1.5"
className="print:stroke-gray-400" className="print:stroke-gray-400"
/> />
{/* Three-line label text */} {/* Three-line label text - smaller sizes */}
<text <text
x={lineEndX} x={lineEndX}
y={y - 20} y={y - 14}
textAnchor={textAnchor} textAnchor={textAnchor}
className="text-sm font-semibold fill-slate-700 print:text-xs" className="fill-slate-700 print:text-[7px]"
style={{ fontSize: '14px', fontWeight: 600 }} style={{ fontSize: '10px', fontWeight: 600 }}
> >
{name} {name}
</text> </text>
<text <text
x={lineEndX} x={lineEndX}
y={y - 4} y={y - 2}
textAnchor={textAnchor} textAnchor={textAnchor}
className="text-xs fill-slate-600 print:text-[10px]" className="fill-slate-600 print:text-[6px]"
style={{ fontSize: '12px' }} style={{ fontSize: '9px' }}
> >
{tons} tons {tons} tons
</text> </text>
<text <text
x={lineEndX} x={lineEndX}
y={y + 12} y={y + 10}
textAnchor={textAnchor} textAnchor={textAnchor}
className="text-xs font-bold fill-slate-800 print:text-[10px]" className="fill-slate-800 print:text-[6px]"
style={{ fontSize: '12px', fontWeight: 700 }} style={{ fontSize: '9px', fontWeight: 700 }}
> >
{percentage.toFixed(1)}% {percentage.toFixed(1)}%
</text> </text>
@ -115,42 +115,44 @@ export function RechartsPortfolioPieChart({
}; };
return ( return (
<div className="flex flex-col items-center w-full"> <div className="flex flex-col items-center w-full max-w-4xl mx-auto">
{/* SVG Chart */} {/* SVG Chart - Responsive container */}
<ResponsiveContainer width={size * 2.2} height={size * 1.4}> <div className="w-full print:max-w-[600px]" style={{ maxWidth: '700px' }}>
<PieChart> <ResponsiveContainer width="100%" height={400} className="print:h-[350px]">
<Pie <PieChart>
data={chartData} <Pie
cx="50%" data={chartData}
cy="50%" cx="50%"
labelLine={false} cy="50%"
label={renderCustomLabel} labelLine={false}
outerRadius={size * 0.35} label={renderCustomLabel}
innerRadius={size * 0.20} outerRadius={80}
paddingAngle={2} innerRadius={50}
dataKey="value" paddingAngle={2}
isAnimationActive={false} dataKey="value"
> isAnimationActive={false}
{chartData.map((entry, index) => ( >
<Cell key={`cell-${index}`} fill={entry.fill} stroke="white" strokeWidth={2} /> {chartData.map((entry, index) => (
))} <Cell key={`cell-${index}`} fill={entry.fill} stroke="white" strokeWidth={2} />
{/* Center label showing total */} ))}
<Label {/* Center label showing total */}
value={totalTons.toString()} <Label
position="center" value={totalTons.toString()}
className="text-2xl font-bold fill-emerald-600 print:text-xl" position="center"
style={{ fontSize: '24px', fontWeight: 700, fill: '#059669' }} className="text-2xl font-bold fill-emerald-600 print:text-xl"
/> style={{ fontSize: '20px', fontWeight: 700, fill: '#059669' }}
<Label />
value="tons CO₂" <Label
position="center" value="tons CO₂"
dy={20} position="center"
className="text-sm fill-slate-600 print:text-xs" dy={18}
style={{ fontSize: '14px', fill: '#475569' }} className="text-sm fill-slate-600 print:text-xs"
/> style={{ fontSize: '12px', fill: '#475569' }}
</Pie> />
</PieChart> </Pie>
</ResponsiveContainer> </PieChart>
</ResponsiveContainer>
</div>
{/* Legend below chart (for print clarity) */} {/* Legend below chart (for print clarity) */}
<div className="mt-6 grid grid-cols-1 md:grid-cols-2 gap-3 w-full max-w-2xl print:mt-4 print:gap-2"> <div className="mt-6 grid grid-cols-1 md:grid-cols-2 gap-3 w-full max-w-2xl print:mt-4 print:gap-2">