Fixed radial chart

This commit is contained in:
2025-12-31 05:04:01 +01:00
parent 1b0b60e01a
commit 46a42b715d
+55 -57
View File
@@ -1,20 +1,5 @@
"use client"; "use client";
import {
Label,
PolarGrid,
PolarRadiusAxis,
RadialBar,
RadialBarChart,
} from "recharts";
import { ChartContainer, type ChartConfig } from "@/components/ui/chart";
const chartConfig = {
value: {
label: "Value",
},
} satisfies ChartConfig;
export default function RadialChart({ export default function RadialChart({
value, value,
children, children,
@@ -22,57 +7,70 @@ export default function RadialChart({
value: number; value: number;
children?: React.ReactNode; children?: React.ReactNode;
}) { }) {
const chartData = [{ value, fill: "var(--color-chart-1)" }]; const radius = 42;
const stroke = 10;
const circumference = 2 * Math.PI * radius;
const TRIM_ANGLE = 80;
const ARC_ANGLE = 360 - TRIM_ANGLE;
const progress = Math.min(Math.max(value, 0), 100);
const arcLength = circumference * (ARC_ANGLE / 360);
const offset = arcLength * (1 - progress / 100);
return ( return (
<ChartContainer config={chartConfig} className="w-full aspect-square"> <div className="w-full aspect-square">
<RadialBarChart <svg viewBox="0 0 100 100" className="w-full h-full">
data={chartData} {/* background arc */}
startAngle={230 - 360 * (value / 100)} <circle
endAngle={230} cx="50"
innerRadius={80} cy="50"
outerRadius={110} r={radius}
> fill="none"
<PolarGrid stroke="var(--muted)"
gridType="circle" strokeWidth={stroke}
radialLines={false} strokeLinecap="round"
stroke="none" strokeDasharray={`${arcLength} ${circumference}`}
className="first:fill-muted last:fill-background" strokeDashoffset={0}
polarRadius={[86, 74]} transform="rotate(130 50 50)"
/> />
<RadialBar dataKey="value" background cornerRadius={10} />
<PolarRadiusAxis tick={false} tickLine={false} axisLine={false}> {/* progress arc */}
<Label <circle
content={({ viewBox }) => { cx="50"
if (viewBox && "cx" in viewBox && "cy" in viewBox) { cy="50"
return ( r={radius}
fill="none"
stroke="var(--color-chart-1)"
strokeWidth={stroke}
strokeLinecap="round"
strokeDasharray={`${arcLength} ${circumference}`}
strokeDashoffset={offset}
transform="rotate(130 50 50)"
/>
{/* center text */}
<text <text
x={viewBox.cx} x="50"
y={viewBox.cy} y="50"
textAnchor="middle" textAnchor="middle"
dominantBaseline="middle" dominantBaseline="middle"
className="fill-foreground text-sm font-bold"
> >
<tspan {value.toFixed(1)}%
x={viewBox.cx} </text>
y={viewBox.cy}
className="fill-foreground text-xl font-bold" {children && (
> <text
{chartData[0].value.toFixed(1)}% x="50"
</tspan> y="67"
<tspan textAnchor="middle"
x={viewBox.cx} className="fill-muted-foreground text-xs"
y={(viewBox.cy || 0) + 24}
className="fill-muted-foreground"
> >
{children} {children}
</tspan>
</text> </text>
); )}
} </svg>
}} </div>
/>
</PolarRadiusAxis>
</RadialBarChart>
</ChartContainer>
); );
} }