KPICard
KPICard groups multiple related metrics inside one compact card.
Quick Start
from faststrap import KPICard
KPICard(
"Campaign Health",
metrics=[
("Leads", "1,240", "+18%", "up"),
("CAC", "$42", "-6%", "up"),
("Churn", "2.1%", "+0.4%", "down"),
],
columns=3,
)
Each metric must include at least (label, value).
("Revenue", "$82k")
("Revenue", "$82k", "+12%", "up")
The optional fourth value must be one of up, down, or neutral. Unknown values are treated as neutral.
Parameters
| Parameter |
Type |
Default |
Description |
title |
str |
required |
Card label. |
metrics |
Sequence[Sequence[Any]] |
required |
Metric tuples. |
columns |
int |
2 |
Number of metric columns. Must be at least 1. |
variant |
Bootstrap variant |
UNSET |
Card background variant. |
inverse |
bool |
False |
Use inverted text colors. |
**kwargs |
Any |
|
Extra HTML attributes. |
API Reference
faststrap.components.display.stat_card.KPICard(title, metrics, columns=2, variant=UNSET, inverse=False, **kwargs)
Card that displays multiple KPIs in a compact grid.
Source code in src/faststrap/components/display/stat_card.py
| @register(category="display")
@beta
def KPICard(
title: str,
metrics: Sequence[Sequence[Any]],
columns: int = 2,
variant: VariantType | None = UNSET,
inverse: bool = False,
**kwargs: Any,
) -> Div:
"""Card that displays multiple KPIs in a compact grid."""
user_cls = kwargs.pop("cls", "")
kwargs["cls"] = merge_classes("faststrap-kpi-card", user_cls)
cfg = resolve_defaults(
"KPICard",
columns=columns,
variant=variant,
inverse=inverse,
)
c_columns = cfg.get("columns", columns)
c_variant = cfg.get("variant", variant)
c_inverse = cfg.get("inverse", inverse)
if c_columns < 1:
msg = f"columns must be >= 1, got {c_columns}"
raise ValueError(msg)
title_cls = "text-muted small text-uppercase fw-semibold"
if c_inverse:
title_cls = "text-white-50 small text-uppercase fw-semibold"
title_el = P(title, cls=title_cls)
metric_cells: list[Any] = []
col_class = f"col-{12 // min(c_columns, 12)}"
for metric in metrics:
if len(metric) < 2:
msg = "Each metric must include at least (label, value)."
raise ValueError(msg)
label = metric[0]
value = metric[1]
delta = metric[2] if len(metric) > 2 else None
delta_type_raw = metric[3] if len(metric) > 3 else "neutral"
if delta_type_raw not in {"up", "down", "neutral"}:
delta_type_raw = "neutral"
delta_type = cast(Literal["up", "down", "neutral"], delta_type_raw)
delta_el = _trend_badge(delta, delta_type=delta_type)
metric_cells.append(
Div(
P(label, cls="mb-1 text-muted small"),
H3(value, cls="mb-0 fw-bold"),
delta_el,
cls=col_class,
)
)
body_content = Div(
title_el,
Div(*metric_cells, cls="row g-3"),
)
return Card(body_content, variant=c_variant, inverse=c_inverse, **kwargs)
|