Skip to content

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,
)

Metric Tuple Format

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.

Usage Scenarios

Dashboard Grid

DashboardGrid(
    KPICard(
        "Revenue",
        [
            ("Today", "$4,200", "+3.2%", "up"),
            ("MTD", "$82k", "+12%", "up"),
            ("Customers", "1,247", "+8%", "up"),
        ],
        columns=3,
        variant="primary",
        inverse=True,
    ),
    cols=12,
)

Dark Mode

KPICard(
    "Server Health",
    [
        ("CPU", "42%", "-5%", "up"),
        ("Memory", "6.2 GB", "+0.3 GB", "down"),
        ("Uptime", "99.98%", "+0.01%", "up"),
    ],
    columns=3,
    inverse=True,
)

Theming

KPICard adds the faststrap-kpi-card class, so you can style it with normal CSS or theme_variant_css().

Accessibility

  • KPICard uses semantic heading markup for the title.
  • Ensure sufficient color contrast for delta values, especially when using inverse=True.

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)