Dashboard KPI widget built on top of the Card and Badge primitives.
A stat_card displays a single key performance indicator with:
- A metric title (e.g. "Monthly Revenue")
- A prominent numeric value (e.g. "$12,345")
- An optional trend badge showing direction and percentage change
- An optional description providing comparison context
- An optional icon slot in the header (top-right corner)
- An optional footer slot for timestamps, sparklines, or extra notes
When to use
Use stat_card on executive dashboards, BI panels, financial terminals, and
any view where at-a-glance KPI monitoring is the primary goal. Combine
multiple cards inside metric_grid/1 for a responsive multi-column layout.
Trend variants
:trend | Badge variant | Icon rendered | Typical use |
|---|---|---|---|
:up | :default | trending-up | Positive growth |
:down | :destructive | trending-down | Decline or regression |
:neutral | :secondary | minus | Flat / no change |
Basic example
<.stat_card
title="Total Revenue"
value="$12,345"
trend={:up}
trend_value="+12%"
description="vs. last month"
/>With icon and footer slots
<.stat_card
title="Active Users"
value="1,024"
trend={:down}
trend_value="-3%"
description="vs. last 30 days"
>
<:icon><.icon name="users" /></:icon>
<:footer>Last updated 2 min ago</:footer>
</.stat_card>Full dashboard row with metric_grid
<.metric_grid cols={4}>
<.stat_card title="Revenue" value="$48,295" trend={:up} trend_value="+18%" description="vs. last quarter" />
<.stat_card title="New Users" value="3,847" trend={:up} trend_value="+7%" description="vs. last month" />
<.stat_card title="Churn Rate" value="2.4%" trend={:down} trend_value="-0.3%" description="vs. last month" />
<.stat_card title="NPS" value="62" trend={:neutral} trend_value="→" description="no change" />
</.metric_grid>Accessibility
The trend badge icon is purely decorative (aria-hidden on the icon
itself). Screen readers will read the trend_value text directly, which
should be self-explanatory (e.g. "+12%" or "-3%").
Summary
Functions
Renders a single KPI stat card.
Functions
Renders a single KPI stat card.
The card layout is a standard PhiaUI Card with three regions:
┌──────────────────────────────────────────────┐
│ card_header │
│ ┌─────────────────────┐ ┌───────────────┐ │
│ │ title (muted text) │ │ icon | badge │ │
│ └─────────────────────┘ └───────────────┘ │
├──────────────────────────────────────────────┤
│ card_content │
│ value (2xl bold) │
│ description (xs muted) │
├──────────────────────────────────────────────┤
│ card_footer (only when footer slot used) │
└──────────────────────────────────────────────┘Attributes
title(:string) (required) - Metric label shown above the value intext-sm text-muted-foreground. Keep it short (2–4 words): "Monthly Revenue", "Active Users", "Churn Rate".value(:string) (required) - The main metric value rendered intext-2xl font-bold. Pass a pre-formatted string:"$12,345","1,024","98.6%". Formatting is left to the caller so locale, currency symbol, and precision remain in application code.trend(:atom) - Direction of the trend indicator. Controls both the badge color variant and the icon rendered inside the badge. Only visible whentrend_valueis also provided.Defaults to
:neutral. Must be one of:up,:down, or:neutral.trend_value(:string) - Text displayed inside the trend badge (e.g."+12%","-3%","→"). Whennil(default), the badge is not rendered at all — useful for metrics where trend comparison is not yet available.Defaults to
nil.description(:string) - Secondary context text rendered below the value intext-xs text-muted-foreground. Typically a comparison period:"vs. last month","year to date","30-day avg". Whennil, no description paragraph is rendered.Defaults to
nil.delta(:string) - Delta value forBadgeDelta(e.g. "+12%"). Requiresdelta_typeto render. Defaults tonil.delta_type(:atom) - Delta type forBadgeDelta. Rendered only when bothdeltaanddelta_typeare set. Defaults tonil. Must be one of:increase,:moderate_increase,:decrease,:moderate_decrease,:unchanged, ornil.sparkline_data(:list) - List of numbers for a mini sparkline SVG in the card footer. Defaults to[].href(:string) - Optional URL. When set, wraps the card in an<a>link. Defaults tonil.class(:string) - Additional CSS classes applied to the outer card. Defaults tonil.Global attributes are accepted. HTML attributes forwarded to the outer card element (e.g.
phx-click,data-*).
Slots
icon- Optional icon displayed in the top-right corner of the card header. Rendered next to the trend badge. Use a small icon (16–20 px):<:icon><.icon name="dollar-sign" /></:icon>When both an icon and a trend badge are present, the icon appears first (left) and the badge appears second (right).
footer- Optional content rendered at the bottom of the card intext-xs text-muted-foreground. Use for timestamps, data source labels, or inline sparkline charts:<:footer>Updated 2 min ago</:footer> <:footer><canvas id="sparkline-mrr" phx-hook="Sparkline" /></:footer>