ui · Primitive
StatCard
@devalok/shilp-sutra/ui/stat-cardView in Storybook 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
LinkContextto resolve framework-specific Link components (Next.js, react-router). Sethrefin a LinkProvider-wrapped tree to get seamless client-side navigation without custom asChild wiring. - Interactive modes:
onClickmakes the entire card a button;hrefmakes it a link. Mutually exclusive — href wins if both are set. - Accent bar semantic: Use
accentto 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 }>ORReactNode. 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
labelandtitleare aliases — use either, not bothonClickandhrefare mutually exclusive — href takes precedencesparklineneeds at least 2 data points to render
Changes
v0.2.0
- Added
iconprop now acceptsReact.ComponentType(e.g.,icon={IconBolt}) in addition toReactNode
v0.1.0
- Added Initial release