init
This commit is contained in:
commit
c19b910c36
80 changed files with 16134 additions and 0 deletions
40
app/components/BudgetMeter.tsx
Normal file
40
app/components/BudgetMeter.tsx
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
import { formatUsd } from "@/app/lib/units";
|
||||
|
||||
/** Herb sage under 85%, saffron amber up to 100%, chili red over budget. */
|
||||
function budgetTone(spent: number, budget: number) {
|
||||
const ratio = budget > 0 ? spent / budget : 0;
|
||||
if (ratio > 1) return { bar: "bg-status-danger", text: "text-status-danger", label: "Over budget" };
|
||||
if (ratio > 0.85) return { bar: "bg-status-warn", text: "text-status-warn", label: "Close to budget" };
|
||||
return { bar: "bg-status-ok", text: "text-status-ok", label: "Under budget" };
|
||||
}
|
||||
|
||||
interface BudgetMeterProps {
|
||||
spent: number;
|
||||
budget: number;
|
||||
compact?: boolean;
|
||||
}
|
||||
|
||||
export function BudgetMeter({ spent, budget, compact = false }: BudgetMeterProps) {
|
||||
const tone = budgetTone(spent, budget);
|
||||
const percent = budget > 0 ? Math.min(100, (spent / budget) * 100) : 0;
|
||||
|
||||
return (
|
||||
<div className={compact ? "w-full" : "w-full min-w-48"}>
|
||||
<div className="flex items-baseline justify-between gap-2 text-xs">
|
||||
<span className={`font-mono text-sm font-semibold tabular-nums ${tone.text}`}>{formatUsd(spent)}</span>
|
||||
<span className="font-mono text-ink-muted tabular-nums">/ {formatUsd(budget)}</span>
|
||||
</div>
|
||||
<div
|
||||
className="mt-1.5 h-2 w-full overflow-hidden rounded-full border border-line-strong/40 bg-raised"
|
||||
role="meter"
|
||||
aria-label="Budget used"
|
||||
aria-valuemin={0}
|
||||
aria-valuemax={budget}
|
||||
aria-valuenow={Math.round(spent * 100) / 100}
|
||||
aria-valuetext={`${formatUsd(spent)} of ${formatUsd(budget)}, ${tone.label.toLowerCase()}`}
|
||||
>
|
||||
<div className={`h-full rounded-full transition-[width] duration-300 ${tone.bar}`} style={{ width: `${percent}%` }} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue