Skip to content

TrendCard

TrendCard is a metric card with a sparkline slot. It is useful when the value matters, but the direction of movement matters too.

Quick Start

from faststrap import TrendCard

TrendCard(
    "Active Users",
    "18.2k",
    delta="+8.1%",
    delta_type="up",
    sparkline=MiniSparkline(),
)

Raw SVG Sparklines

Raw string sparklines are blocked by default. Set sparkline_safe=True only for trusted SVG/HTML.

TrendCard(
    "Latency",
    "184ms",
    delta="-12ms",
    delta_type="up",
    sparkline="<svg><!-- trusted svg --></svg>",
    sparkline_safe=True,
)

Parameters

Parameter Type Default Description
title str required Metric label.
value str \| int \| float required Primary metric value.
sparkline Any \| None None Sparkline element or trusted raw string.
sparkline_safe bool False Required before embedding raw string sparkline markup.
delta str \| int \| float \| None None Change text such as +8%.
delta_type "up" \| "down" \| "neutral" "neutral" Delta color treatment.
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.TrendCard(title, value, sparkline=None, sparkline_safe=False, delta=None, delta_type='neutral', variant=UNSET, inverse=False, **kwargs)

Metric card with a sparkline slot for trends.

Source code in src/faststrap/components/display/stat_card.py
@register(category="display")
@beta
def TrendCard(
    title: str,
    value: str | int | float,
    sparkline: Any | None = None,
    sparkline_safe: bool = False,
    delta: str | int | float | None = None,
    delta_type: Literal["up", "down", "neutral"] = "neutral",
    variant: VariantType | None = UNSET,
    inverse: bool = False,
    **kwargs: Any,
) -> Div:
    """Metric card with a sparkline slot for trends."""
    user_cls = kwargs.pop("cls", "")
    kwargs["cls"] = merge_classes("faststrap-trend-card", user_cls)

    cfg = resolve_defaults(
        "TrendCard",
        delta_type=delta_type,
        variant=variant,
        inverse=inverse,
    )
    c_delta_type = cfg.get("delta_type", delta_type)
    c_variant = cfg.get("variant", variant)
    c_inverse = cfg.get("inverse", inverse)

    delta_el = _trend_badge(delta, delta_type=c_delta_type)
    value_el = H3(value, cls="mb-0 fw-bold")
    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)

    sparkline_el = None
    if sparkline is not None:
        if isinstance(sparkline, str):
            if not sparkline_safe:
                msg = "sparkline_safe=True is required to embed raw HTML/SVG sparklines."
                raise ValueError(msg)
            from fasthtml.common import NotStr

            sparkline_el = Div(NotStr(sparkline), cls="text-end")
        else:
            sparkline_el = Div(sparkline, cls="text-end")

    body_content = Div(
        Div(title_el, value_el, delta_el, cls="flex-grow-1"),
        sparkline_el,
        cls="d-flex align-items-center justify-content-between gap-3",
    )

    return Card(body_content, variant=c_variant, inverse=c_inverse, **kwargs)