ui · Primitive

StatCard

@devalok/shilp-sutra/ui/stat-cardView in Storybook
Live preview coming

Hand-curated previews ship in rolling waves. See it live in Storybook →

Reference

Props

label: string (heading text)
title: string (alias for label)
value: string | number (REQUIRED)
prefix: string (before value, e.g. "$")
suffix: string (after value, e.g. "users")
delta: { value: string, direction: "up" | "down" | "neutral" }
icon: ReactNode | ComponentType<{ className?: string }>
loading: boolean (renders skeleton)
comparisonLabel: string (shown after delta, e.g. "vs last month")
secondaryLabel: string (below main value, e.g. "of $50,000 target")
progress: number (0-100, renders thin progress bar below value)
accent: "default" | "success" | "warning" | "error" | "info" (left border color)
sparkline: number[] (renders mini SVG line chart)
onClick: () => void (makes card clickable with hover state)
href: string (makes card a link via LinkContext)
footer: ReactNode (below card body, e.g. "View details →")

Defaults

none (all props are optional except value)

Example

<StatCard
  label="Revenue"
  value="$48,200"
  prefix="$"
  delta={{ value: "+12%", direction: "up" }}
  comparisonLabel="vs last month"
  icon={<IconCurrencyDollar />}
  accent="success"
/>

<StatCard
  label="Storage"
  value="4.2 GB"
  secondaryLabel="of 10 GB"
  progress={42}
  sparkline={[10, 25, 18, 30, 42]}
  footer={<a href="/storage">Manage storage →</a>}
/>

Composability

  • High-density metric card — optimized for dashboards. Everything optional except value. Mix and match features (delta, sparkline, progress, secondary label, footer) per metric's needs.
  • Router integration via href: Internally uses LinkContext to resolve framework-specific Link components (Next.js, react-router). Set href in a LinkProvider-wrapped tree to get seamless client-side navigation without custom asChild wiring.
  • Interactive modes: onClick makes the entire card a button; href makes it a link. Mutually exclusive — href wins if both are set.
  • Accent bar semantic: Use accent to signal metric health at a glance (success for positive, warning for at-risk, error for over-target). Combine with delta.direction for layered emphasis.
  • Sparkline: Pure SVG, lightweight — no chart library. For rich charts use Chart components. Minimum 2 data points.
  • Icon auto-sizing: Accepts ComponentType<{ className }> OR ReactNode. The component prop (e.g. icon={IconBolt}) is preferred — icon is rendered at a consistent size.
  • Loading state: loading={true} renders the full card skeleton — use during initial data fetch.

Gotchas

  • delta.direction "up" = green, "down" = red, "neutral" = grey
  • label and title are aliases — use either, not both
  • onClick and href are mutually exclusive — href takes precedence
  • sparkline needs at least 2 data points to render

Changes

v0.2.0

  • Added icon prop now accepts React.ComponentType (e.g., icon={IconBolt}) in addition to ReactNode

v0.1.0

  • Added Initial release