Fixed radial chart

This commit is contained in:
2025-12-31 05:04:01 +01:00
parent 1b0b60e01a
commit 46a42b715d
+62 -64
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}
<text fill="none"
x={viewBox.cx} stroke="var(--color-chart-1)"
y={viewBox.cy} strokeWidth={stroke}
textAnchor="middle" strokeLinecap="round"
dominantBaseline="middle" strokeDasharray={`${arcLength} ${circumference}`}
> strokeDashoffset={offset}
<tspan transform="rotate(130 50 50)"
x={viewBox.cx} />
y={viewBox.cy}
className="fill-foreground text-xl font-bold" {/* center text */}
> <text
{chartData[0].value.toFixed(1)}% x="50"
</tspan> y="50"
<tspan textAnchor="middle"
x={viewBox.cx} dominantBaseline="middle"
y={(viewBox.cy || 0) + 24} className="fill-foreground text-sm font-bold"
className="fill-muted-foreground" >
> {value.toFixed(1)}%
{children} </text>
</tspan>
</text> {children && (
); <text
} x="50"
}} y="67"
/> textAnchor="middle"
</PolarRadiusAxis> className="fill-muted-foreground text-xs"
</RadialBarChart> >
</ChartContainer> {children}
</text>
)}
</svg>
</div>
); );
} }