49 lines
1.7 KiB
TypeScript
49 lines
1.7 KiB
TypeScript
"use client";
|
|
|
|
import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip";
|
|
|
|
/**
|
|
* Small pie-chart badge pinned to a Group card's bottom-right corner,
|
|
* showing what fraction of its to-dos are complete. `completed`/`total`
|
|
* come straight from the group's own to-do list, so it's recalculated and
|
|
* redrawn on every render -- any add/toggle/delete that changes those
|
|
* numbers repaints this automatically, with no separate update path to
|
|
* keep in sync.
|
|
*/
|
|
export function TodoProgressPie({
|
|
completed,
|
|
total,
|
|
accentColor,
|
|
}: {
|
|
completed: number;
|
|
total: number;
|
|
accentColor: string;
|
|
}) {
|
|
if (total === 0) return null;
|
|
const pct = Math.round((completed / total) * 100);
|
|
// Same hue as the stroke and the "completed" wedge, just faded into the
|
|
// card surface -- so the remaining wedge reads as an absence of
|
|
// progress rather than a second, competing color.
|
|
const emptyColor = `color-mix(in srgb, ${accentColor} 22%, var(--card))`;
|
|
|
|
return (
|
|
<Tooltip>
|
|
<TooltipTrigger
|
|
render={
|
|
<div
|
|
role="img"
|
|
aria-label={`${pct}% of to-dos completed`}
|
|
tabIndex={0}
|
|
className="absolute -right-1.5 -bottom-1.5 size-7 shrink-0 cursor-default rounded-full border-2 shadow-sm outline-none transition-transform hover:scale-110 focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1"
|
|
style={{
|
|
borderColor: accentColor,
|
|
background: `conic-gradient(${accentColor} ${pct}%, ${emptyColor} ${pct}% 100%)`,
|
|
}}
|
|
/>
|
|
}
|
|
/>
|
|
<TooltipContent side="top">{pct}% To-Dos Completed</TooltipContent>
|
|
</Tooltip>
|
|
);
|
|
}
|