Responsive CSS Grid wrapper for stat_card/1 KPI widgets.
metric_grid/1 takes care of the responsive column math so you do not have
to hand-craft Tailwind breakpoint classes for every dashboard. Pass the
desired maximum column count and the grid automatically collapses to fewer
columns on smaller screens.
Column breakpoints
:cols | Mobile (< sm) | Tablet (sm+) | Desktop (lg+) |
|---|---|---|---|
1 | 1 | 1 | 1 |
2 | 1 | 2 | 2 |
3 | 1 | 2 | 3 |
4 | 1 | 2 | 4 |
The single-column mobile layout ensures that stat cards never appear side-by-side when they would be too narrow to be readable.
Basic example
<.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>Three-column variant
When a fourth metric is not available or the layout needs more breathing
room, use cols={3}:
<.metric_grid cols={3}>
<.stat_card title="MRR" value="$24,150" trend={:up} trend_value="+11%" />
<.stat_card title="Active Users" value="892" trend={:up} trend_value="+5%" />
<.stat_card title="Avg Session" value="4m 32s" trend={:down} trend_value="-8s" />
</.metric_grid>Mixed content
metric_grid/1 is a plain CSS Grid wrapper — any card-shaped element works
inside it, not just stat_card/1:
<.metric_grid cols={3}>
<.stat_card title="Revenue" value="$12,345" />
<.chart_shell title="Trend" min_height="120px">
<.phia_chart id="mini-chart" type={:area} series={@series} labels={@labels} height="120px" />
</.chart_shell>
<.stat_card title="NPS" value="68" trend={:up} trend_value="+4" />
</.metric_grid>Integration with Shell
Place metric_grid/1 directly inside the <main> of shell/1:
<main class="overflow-y-auto p-6 space-y-6">
<.metric_grid cols={4}>
<%= for kpi <- @kpis do %>
<.stat_card
title={kpi.label}
value={kpi.formatted_value}
trend={kpi.trend}
trend_value={kpi.trend_text}
description={kpi.period}
/>
<% end %>
</.metric_grid>
</main>
Summary
Functions
Renders a responsive CSS Grid wrapper for dashboard KPI cards.
Functions
Renders a responsive CSS Grid wrapper for dashboard KPI cards.
The grid uses gap-4 between cells. Add vertical spacing between this
component and others using a wrapper class or a space-y-* parent.
Example
<.metric_grid cols={4}>
<.stat_card title="Revenue" value="$12,345" trend={:up} trend_value="+8%" />
<.stat_card title="Users" value="1,024" trend={:up} trend_value="+3%" />
<.stat_card title="Churn" value="2.1%" trend={:down} trend_value="-0.4%" />
<.stat_card title="NPS" value="62" trend={:neutral} trend_value="→" />
</.metric_grid>Attributes
cols(:integer) - Maximum number of columns in the grid (1–4). The grid automatically collapses to fewer columns at smaller breakpoints:- Mobile (< sm): always 1 column
- Tablet (sm+): up to 2 columns
- Desktop (lg+): up to the specified
:colsvalue
Defaults to
4. Must be one of1,2,3, or4.class(:string) - Additional CSS classes for the grid wrapper (e.g.mt-6for vertical spacing). Defaults tonil.Global attributes are accepted. HTML attributes forwarded to the wrapper div.
Slots
inner_block(required) -stat_card/1components or other card-shaped children to lay out in the grid.