Files
paperclip/ui/src/components/MetricCard.tsx
Dotta 57dcdb51af ui: apply interface polish from design article review
- 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>
2026-03-11 08:20:24 -05:00

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;
}