Cards cardsstatsanalyticskpidashboard
Stats Trend Card
Modern analytics KPI metric card displaying values, positive/negative delta trend badge, and mini sparkline bar visual.
Preview
Monthly Active Builders ↑ +18.4%
14,290
vs last 30 days
Usage
Copy the full block below to use this component with its imports.
astro
---
import { StatsTrendCard } from 'astro-component-kit';
---
<StatsTrendCard title="Active Subscriptions" value="14,290" change="+12.8%" isPositive={true} subtitle="Compared to previous 30 days" /> ---
import { StatsTrendCard } from 'astro-component-kit';
---
<StatsTrendCard title="Active Subscriptions" value="14,290" change="+12.8%" isPositive={true} subtitle="Compared to previous 30 days" /> Manual Installation
If you are not using the npm package, create a new file src/components/lib/StatsTrendCard.astro and paste the following code:
astro
---
/**
* StatsTrendCard — Compact KPI metric card featuring delta percentages, trend directions, and mini activity bars.
*
* @param {string} label - Metric name (e.g. 'Active Users').
* @param {string} value - Formatted value figure (e.g. '42,850').
* @param {string} change - Delta percentage string (e.g. '+18.4%').
* @param {'up' | 'down' | 'neutral'} trend - Direction of the trend. Default is 'up'.
* @param {string} timeframe - Timeframe subtitle (e.g. 'vs last month').
*/
interface Props {
label: string;
value: string;
change: string;
trend?: 'up' | 'down' | 'neutral';
timeframe?: string;
}
const {
label,
value,
change,
trend = 'up',
timeframe = 'vs last 30 days',
} = Astro.props;
const bars = [35, 55, 40, 75, 60, 90, 80, 100];
---
<div class="trend-card">
<div class="trend-card__top">
<span class="trend-card__label">{label}</span>
<span class:list={['trend-card__badge', `trend-card__badge--${trend}`]}>
{trend === 'up' && '↑'}
{trend === 'down' && '↓'}
{change}
</span>
</div>
<div class="trend-card__value">{value}</div>
<div class="trend-card__bottom">
<span class="trend-card__timeframe">{timeframe}</span>
<div class="trend-card__chart" aria-hidden="true">
{bars.map((h) => (
<span class="bar" style={`height: ${h}%;`}></span>
))}
</div>
</div>
</div>
<style>
.trend-card {
display: flex;
flex-direction: column;
padding: var(--sp-6, 1.5rem);
background: rgba(255, 255, 255, 0.02);
backdrop-filter: blur(16px);
border: 1px solid rgba(255, 255, 255, 0.08);
border-radius: var(--r-xl, 20px);
width: 100%;
max-width: 280px;
font-family: var(--font-sans, system-ui, sans-serif);
transition: transform 0.25s ease, border-color 0.25s ease;
}
.trend-card:hover {
transform: translateY(-2px);
border-color: rgba(184, 134, 11, 0.3);
}
.trend-card__top {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 8px;
}
.trend-card__label {
font-size: 0.8rem;
font-weight: 600;
color: var(--c-text-2, #a3a3a3);
}
.trend-card__badge {
font-size: 0.72rem;
font-weight: 700;
padding: 2px 8px;
border-radius: var(--r-full, 9999px);
display: inline-flex;
align-items: center;
gap: 2px;
}
.trend-card__badge--up {
background: rgba(16, 185, 129, 0.15);
color: #34d399;
border: 1px solid rgba(16, 185, 129, 0.3);
}
.trend-card__badge--down {
background: rgba(239, 68, 68, 0.15);
color: #f87171;
border: 1px solid rgba(239, 68, 68, 0.3);
}
.trend-card__badge--neutral {
background: rgba(255, 255, 255, 0.08);
color: var(--c-text-2, #a3a3a3);
}
.trend-card__value {
font-size: 1.85rem;
font-weight: 900;
color: var(--c-text-1, #ffffff);
letter-spacing: -0.02em;
margin-bottom: 12px;
}
.trend-card__bottom {
display: flex;
justify-content: space-between;
align-items: flex-end;
}
.trend-card__timeframe {
font-size: 0.74rem;
color: var(--c-text-3, #737373);
}
.trend-card__chart {
display: flex;
align-items: flex-end;
gap: 3px;
height: 24px;
width: 60px;
}
.bar {
flex: 1;
background: rgba(184, 134, 11, 0.35);
border-radius: 2px;
transition: background 0.2s;
}
.trend-card:hover .bar {
background: var(--c-primary-light, #d4a017);
}
</style> ---
/**
* StatsTrendCard — Compact KPI metric card featuring delta percentages, trend directions, and mini activity bars.
*
* @param {string} label - Metric name (e.g. 'Active Users').
* @param {string} value - Formatted value figure (e.g. '42,850').
* @param {string} change - Delta percentage string (e.g. '+18.4%').
* @param {'up' | 'down' | 'neutral'} trend - Direction of the trend. Default is 'up'.
* @param {string} timeframe - Timeframe subtitle (e.g. 'vs last month').
*/
interface Props {
label: string;
value: string;
change: string;
trend?: 'up' | 'down' | 'neutral';
timeframe?: string;
}
const {
label,
value,
change,
trend = 'up',
timeframe = 'vs last 30 days',
} = Astro.props;
const bars = [35, 55, 40, 75, 60, 90, 80, 100];
---
<div class="trend-card">
<div class="trend-card__top">
<span class="trend-card__label">{label}</span>
<span class:list={['trend-card__badge', `trend-card__badge--${trend}`]}>
{trend === 'up' && '↑'}
{trend === 'down' && '↓'}
{change}
</span>
</div>
<div class="trend-card__value">{value}</div>
<div class="trend-card__bottom">
<span class="trend-card__timeframe">{timeframe}</span>
<div class="trend-card__chart" aria-hidden="true">
{bars.map((h) => (
<span class="bar" style={`height: ${h}%;`}></span>
))}
</div>
</div>
</div>
<style>
.trend-card {
display: flex;
flex-direction: column;
padding: var(--sp-6, 1.5rem);
background: rgba(255, 255, 255, 0.02);
backdrop-filter: blur(16px);
border: 1px solid rgba(255, 255, 255, 0.08);
border-radius: var(--r-xl, 20px);
width: 100%;
max-width: 280px;
font-family: var(--font-sans, system-ui, sans-serif);
transition: transform 0.25s ease, border-color 0.25s ease;
}
.trend-card:hover {
transform: translateY(-2px);
border-color: rgba(184, 134, 11, 0.3);
}
.trend-card__top {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 8px;
}
.trend-card__label {
font-size: 0.8rem;
font-weight: 600;
color: var(--c-text-2, #a3a3a3);
}
.trend-card__badge {
font-size: 0.72rem;
font-weight: 700;
padding: 2px 8px;
border-radius: var(--r-full, 9999px);
display: inline-flex;
align-items: center;
gap: 2px;
}
.trend-card__badge--up {
background: rgba(16, 185, 129, 0.15);
color: #34d399;
border: 1px solid rgba(16, 185, 129, 0.3);
}
.trend-card__badge--down {
background: rgba(239, 68, 68, 0.15);
color: #f87171;
border: 1px solid rgba(239, 68, 68, 0.3);
}
.trend-card__badge--neutral {
background: rgba(255, 255, 255, 0.08);
color: var(--c-text-2, #a3a3a3);
}
.trend-card__value {
font-size: 1.85rem;
font-weight: 900;
color: var(--c-text-1, #ffffff);
letter-spacing: -0.02em;
margin-bottom: 12px;
}
.trend-card__bottom {
display: flex;
justify-content: space-between;
align-items: flex-end;
}
.trend-card__timeframe {
font-size: 0.74rem;
color: var(--c-text-3, #737373);
}
.trend-card__chart {
display: flex;
align-items: flex-end;
gap: 3px;
height: 24px;
width: 60px;
}
.bar {
flex: 1;
background: rgba(184, 134, 11, 0.35);
border-radius: 2px;
transition: background 0.2s;
}
.trend-card:hover .bar {
background: var(--c-primary-light, #d4a017);
}
</style>
Quick Info
- Category
- Cards
- Filename
StatsTrendCard.astro- Dependencies
- None — pure Astro + CSS
- Tags
- cardsstatsanalyticskpidashboard