---
title: "StatCard"
description: "A card that shows a metric with its trend or progress."
category: Data
status: beta
since: 0.3.4
tags: [stat, metric, dashboard]
syncStatus: reviewed
verified: true
---

## Usage

### Default Variant
A color class in `iconClass` sets the tone (primary by default; grey draws no aura); `meta` adds a line under the label.
::TuffDemoWrapper{demo="StatCardDefaultVariantDemo" code-lang="vue"}
---
code: |
  <template>
    <TxStatCard
      :value="2847"
      label="Total plugins"
      meta="Includes enabled and disabled plugins"
      icon-class="i-carbon-download text-[var(--tx-color-primary)]"
      clickable
    />
    <TxStatCard
      :value="2516"
      label="Enabled"
      icon-class="i-carbon-checkmark-outline text-[var(--tx-color-success)]"
    />
    <TxStatCard
      :value="18"
      label="Pending updates"
      icon-class="i-carbon-renew text-[var(--tx-color-warning)]"
    />
    <TxStatCard
      :value="331"
      label="Disabled"
      icon-class="i-carbon-power text-[var(--tx-color-info)]"
    />
  </template>
---
::

### Insight Variant
`insight` computes the change from `from` and `to` and renders it as a tinted pill; `insight.iconClass` replaces the built-in arrow.
::TuffDemoWrapper{demo="StatCardInsightVariantDemo" code-lang="vue"}
---
code: |
  <script setup lang="ts">
  import { ref } from 'vue'

  const activeUsers = ref(18200)
  const resourceLoad = ref(42)

  const activeInsight = { from: 16800, to: 18200, type: 'delta', color: 'success' }

  const resourceInsight = {
    from: 35,
    to: 42,
    type: 'percent',
    color: 'danger',
    iconClass: 'i-carbon-arrow-up-right',
    precision: 1,
  }
  </script>

  <template>
    <TxStatCard
      :value="activeUsers"
      label="Active Users"
      icon-class="i-carbon-task text-[var(--tx-color-success)]"
      :insight="activeInsight"
    />
    <TxStatCard
      :value="resourceLoad"
      label="Resource Load"
      icon-class="i-carbon-chip text-[var(--tx-color-warning)]"
      :insight="resourceInsight"
    >
      <template #value>
        <TxTextMorph :text="resourceLoad" /><span>%</span>
      </template>
    </TxStatCard>
  </template>
---
::

### Progress Variant
`progress` switches to the progress layout; the ring follows the color in `iconClass`.
::TuffDemoWrapper{demo="StatCardProgressVariantDemo" code-lang="vue"}
---
code: |
  <template>
    <TxStatCard
      variant="progress"
      :value="healthProgress"
      label="Cloud Sync"
      :meta="healthMeta"
      :progress="healthProgress"
      icon-class="i-carbon-cloud text-[var(--tx-color-primary)]"
    >
      <template #value>
        <TxTextMorph :text="healthProgress" /><span>%</span>
      </template>
    </TxStatCard>
  </template>
---
::

### Dashboard Operations Panel
Combines with `TxStatusBadge` and `TxProgressBar` into a dashboard status header.
::TuffDemoWrapper{demo="ComponentsOperationsStatusDemo" code-lang="vue"}
---
code: |
  <template>
    <TxStatCard
      variant="progress"
      value="99.9%"
      label="API availability"
      meta="Normal"
      :progress="99"
      icon-class="i-carbon-cloud-monitoring text-[var(--tx-color-success)]"
    />
    <TxStatCard
      variant="progress"
      :value="18"
      label="Pending queue"
      meta="Watch"
      :progress="64"
      icon-class="i-carbon-queued text-[var(--tx-color-warning)]"
    />
    <TxStatCard
      variant="progress"
      :value="2"
      label="Alerts"
      meta="Blocked"
      :progress="22"
      icon-class="i-carbon-warning-alt text-[var(--tx-color-danger)]"
    />
  </template>
---
::

### Best Practices

- Pass count metrics as numbers so the default formatter adds separators; use the `value` slot for complex units or animated numbers.
- Use `insight.type="delta"` for absolute changes and `insight.type="percent"` for relative ones.
- Reserve `variant="progress"` for bounded values such as health, capacity, quota, or completion, never unbounded totals.
- `clickable` changes only the look; let a surrounding button or link carry navigation and actions.
- Let the parent set the width (a grid cell, a stretched flex item); a shrink-to-fit parent such as `inline-block` collapses the card.

## API Reference

### Props

| Prop | Type | Default | Description |
|------|------|---------|------|
| `value` | `number \| string` | - | Primary value; numbers get the default formatter's separators. |
| `label` | `string` | - | Metric label; shown at the top in the insight and progress layouts. |
| `iconClass` | `string` | `''` | Decorative icon class, sized by the component; its color class tints the icon, aura, and ring. |
| `clickable` | `boolean` | `false` | Adds only the pointer cursor; no click behavior is attached. |
| `insight` | `StatCardInsight` | - | Change indicator; moves the label to the top and renders the trend pill. |
| `variant` | `StatCardVariant` | `'default'` | Layout variant (`default` \| `progress`). |
| `progress` | `number` | - | Progress percent; passing it enables the progress layout, clamped to 0–100. |
| `meta` | `string` | - | Supporting line; the `meta` slot takes precedence. |
| `ariaLabel` | `string` | - | Accessible name of the `role="group"`; defaults to the visible label. |

### Slots

| Slot | Description |
|------|------|
| `value` | Custom value area. |
| `label` | Custom label area. |
| `meta` | Supporting line; with both it and `meta` omitted, no line is reserved. |

### StatCardInsight

| Field | Type | Default | Description |
|------|------|---------|------|
| `from` | `number` | - | Baseline value. |
| `to` | `number` | - | Current value. |
| `type` | `'percent' \| 'delta'` | `'percent'` | Percent change or absolute delta. |
| `color` | `'success' \| 'danger' \| 'warning' \| 'info' \| string` | - | Indicator color, which also tints the pill; defaults to success for ≥ 0 and danger below. |
| `iconClass` | `string` | - | Custom trend icon class; defaults to a built-in SVG arrow. |
| `suffix` | `string` | - | Suffix, `%` by default for percent; it sits flush, so include any space, as in `' pts'`. |
| `precision` | `number` | - | Decimal places; defaults to 0 for `delta` and 1 for `percent`. |

### CSS Variables

| Variable | Source | Description |
|------|------|------|
| `--tx-stat-card-slot` | Component default `72px`; override through the component's `style` | Side of the square right-hand slot that sizes the icon and ring; `36px` on a narrow card. |
| `--tx-stat-card-slot-inset` | Component default `18px`; override through the component's `style` | Distance from the slot to the card's right edge; unused in the narrow layout. |
| `--tx-stat-card-icon-color` | Written by the component (the icon's computed color) | Source color of the aura, glyph ink, and ring; component-owned, so never bind it via `:style`. |

## Overview

- The root is a `role="group"` named by its visible label through `aria-labelledby`; give dashboards a nearby heading so numbers never stand bare.
- On mount, on `iconClass` / `variant` changes, and after a theme switch, the card reads the icon's computed color. A hue adds `tx-stat-card--tinted` and the aura; a grey icon (including `--tx-color-info`) draws none.
- When the card's content box is under 240px (a container query, not the viewport), the slot shrinks to 36px and moves to the top-right corner.
- The insight pill renders sign, number, and unit as one figure (`+16.7%`); numbers use tabular figures and hold still while updating.
- Hover only switches the border to `--tx-border-color`, with no motion.
- Under reduced motion the blobs stop drifting, the aura appears at once, and the progress arc jumps to its value.

## Technologies

- The aura is three blurred blobs that animate `transform` alone, so the compositor moves them without re-blurring each frame.
- Source: `packages/tuffex/packages/components/src/stat-card/`.

<TuffDocSourceLink />
