import type { CSSProperties, ReactNode } from 'react'; import { Sparkline } from './Sparkline.js'; export interface KpiCardProps { /** Metric label (e.g. 'Active users'). */ label: string; /** Pre-formatted display value (e.g. '12.4k', '$8,421'). */ value: ReactNode; /** Delta percentage (e.g. 6.6 for +6.6%). */ deltaPercent?: number; /** Override the delta label (e.g. 'vs last 7d'). */ deltaLabel?: string; /** Inline trend data. Optional. */ trend?: number[]; /** Icon rendered top-right. */ icon?: ReactNode; /** Sparkline stroke override. */ trendColor?: string; /** Hide the up/down arrow next to delta. Default false. */ hideDeltaArrow?: boolean; /** Override the threshold below which a delta is rendered as 'good'. * Useful for cost / latency KPIs where lower is better. Default `>=0`. */ goodWhen?: 'higher' | 'lower'; className?: string; style?: CSSProperties; } /** * `` — token-themed key-performance-indicator tile. * * ┌────────────────────────┐ * │ Active users ✦ │ * │ 8,421 │ * │ ▲ +6.6% vs last 7d ╱╲╱ │ * └────────────────────────┘ * * Renders the headline number prominently, an optional delta with * color-coded arrow, and an inline `` for context. */ export function KpiCard({ label, value, deltaPercent, deltaLabel = 'vs previous', trend, icon, trendColor, hideDeltaArrow, goodWhen = 'higher', className, style, }: KpiCardProps) { const hasDelta = typeof deltaPercent === 'number'; const up = hasDelta && deltaPercent! >= 0; const good = !hasDelta || (goodWhen === 'higher' ? up : !up && Math.abs(deltaPercent!) > 0.0001); const deltaColor = good ? 'var(--bl-success, #22c55e)' : 'var(--bl-danger, #ef4444)'; return (
{label} {icon && ( {icon} )}
{value}
{hasDelta && ( {!hideDeltaArrow && {up ? '▲' : '▼'}} {(up ? '+' : '') + deltaPercent!.toFixed(1)}% )} {hasDelta && ( {deltaLabel} )} {trend && trend.length > 1 && (
)}
); }