- Add global font smoothing (antialiased) to body - Add tabular-nums to all numeric displays: MetricCard values, Costs page, AgentDetail token/cost grids and tables, IssueDetail cost summary, Companies page budget display - Replace markdown image hard border with subtle inset box-shadow overlay - Replace all animate-ping status dots with calmer animate-pulse across AgentDetail, IssueDetail, Agents, sidebar, kanban, issues list, and active agents panel Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
54 lines
1.5 KiB
TypeScript
54 lines
1.5 KiB
TypeScript
import type { LucideIcon } from "lucide-react";
|
|
import type { ReactNode } from "react";
|
|
import { Link } from "@/lib/router";
|
|
|
|
interface MetricCardProps {
|
|
icon: LucideIcon;
|
|
value: string | number;
|
|
label: string;
|
|
description?: ReactNode;
|
|
to?: string;
|
|
onClick?: () => void;
|
|
}
|
|
|
|
export function MetricCard({ icon: Icon, value, label, description, to, onClick }: MetricCardProps) {
|
|
const isClickable = !!(to || onClick);
|
|
|
|
const inner = (
|
|
<div className={`h-full px-4 py-4 sm:px-5 sm:py-5 rounded-lg transition-colors${isClickable ? " hover:bg-accent/50 cursor-pointer" : ""}`}>
|
|
<div className="flex items-start justify-between gap-3">
|
|
<div className="flex-1 min-w-0">
|
|
<p className="text-2xl sm:text-3xl font-semibold tracking-tight tabular-nums">
|
|
{value}
|
|
</p>
|
|
<p className="text-xs sm:text-sm font-medium text-muted-foreground mt-1">
|
|
{label}
|
|
</p>
|
|
{description && (
|
|
<div className="text-xs text-muted-foreground/70 mt-1.5 hidden sm:block">{description}</div>
|
|
)}
|
|
</div>
|
|
<Icon className="h-4 w-4 text-muted-foreground/50 shrink-0 mt-1.5" />
|
|
</div>
|
|
</div>
|
|
);
|
|
|
|
if (to) {
|
|
return (
|
|
<Link to={to} className="no-underline text-inherit h-full" onClick={onClick}>
|
|
{inner}
|
|
</Link>
|
|
);
|
|
}
|
|
|
|
if (onClick) {
|
|
return (
|
|
<div className="h-full" onClick={onClick}>
|
|
{inner}
|
|
</div>
|
|
);
|
|
}
|
|
|
|
return inner;
|
|
}
|