# Stats Band

> Headline figures on a dark band, each with a label, a footnote and a source line.

- **Slug:** `stats-band`
- **Kind:** section · **Category:** Proof
- **Source:** original to Viewership UI
- **Docs page:** https://viewership.ai/design/components/stats-band
- **All files in one bundle:** https://viewership.ai/design/components/stats-band.bundle.txt
- **Structured JSON:** https://viewership.ai/design/components/stats-band.json

## Install

1. Import the foundation tokens once (download: https://viewership.ai/design/raw/foundation.css.txt):

```astro
---
// src/layouts/Layout.astro
import "../styles/foundation.css";
---
```

2. Copy this file into `src/components/viewership/stats-band/`:

   - `StatsBand.astro` (raw: https://viewership.ai/design/raw/stats-band/StatsBand.astro.txt)

npm packages: none.

## Usage

```astro
---
import StatsBand from "../components/viewership/stats-band/StatsBand.astro";
---

<StatsBand />
```

## Example

The gallery demo, verbatim. Use the import path from Usage instead of `./`.

```astro
---
import StatsBand from "./StatsBand.astro";
---

<StatsBand
  title="The repair bench, last year"
  stats={[
    { value: "11,400", label: "Repairs completed", note: "Up from 8,900" },
    { value: "2.1", label: "Days average turnaround" },
    { value: "94%", label: "Fixed, not replaced" },
    { value: "3,200", label: "Packs resold" },
  ]}
  source="Sample figures for a fictional brand."
/>
```

## Props

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `title` | `string` |  | Small heading above the figures. |
| `stats` | `{ value: string; label: string; note?: string }[]` |  | Figures. Three or four read best. |
| `source` | `string` |  | Where the numbers come from. |
| `tone` | `"ink" \| "page"` | `"ink"` | Dark band or page ground. |
| `as` | `"h2" \| "h3"` | `"h2"` | Heading element. |

## Source

### `src/components/viewership/stats-band/StatsBand.astro`

```astro
---
/**
 * StatsBand: a few headline figures on a dark band, each with a label and an
 * optional footnote. Use real, sourced numbers only.
 *
 * @example
 * <StatsBand title="The bench in numbers" stats={[{ value: "11,400", label: "Repairs last year" }]} />
 */
interface Stat {
  value: string;
  label: string;
  note?: string;
}
interface Props {
  title?: string;
  stats: Stat[];
  /** Source or date line under the figures. */
  source?: string;
  /** "ink" sits on a dark band; "page" uses the page ground. */
  tone?: "ink" | "page";
  as?: "h2" | "h3";
  class?: string;
}

const { title, stats, source, tone = "ink", as: Heading = "h2", class: className } = Astro.props;
---

<section class:list={["vs-stats-band", `vs-stats-band--${tone}`, className]}>
  <div class="vs-stats-band__inner">
    {title && <Heading class="vs-stats-band__title">{title}</Heading>}
    <dl class="vs-stats-band__grid">
      {
        stats.map((s) => (
          <div class="vs-stats-band__stat">
            <dt class="vs-stats-band__label">{s.label}</dt>
            <dd class="vs-display vs-stats-band__value">{s.value}</dd>
            {s.note && <dd class="vs-stats-band__note">{s.note}</dd>}
          </div>
        ))
      }
    </dl>
    {source && <p class="vs-stats-band__source">{source}</p>}
  </div>
</section>

<style>
  .vs-stats-band {
    container-type: inline-size;
    background: var(--vs-page);
    color: var(--vs-ink);
    font-family: var(--vs-font-sans);
    font-stretch: var(--vs-font-stretch);
    --vs-stats-muted: var(--vs-ink-2);
    --vs-stats-rule: var(--vs-line-strong);
  }
  .vs-stats-band--ink {
    background: var(--vs-ink);
    color: var(--vs-ink-inverse);
    --vs-stats-muted: color-mix(in srgb, var(--vs-ink-inverse) 65%, transparent);
    --vs-stats-rule: color-mix(in srgb, var(--vs-ink-inverse) 22%, transparent);
  }
  .vs-stats-band__inner {
    max-width: var(--vs-container);
    margin-inline: auto;
    padding: clamp(48px, 8cqi, 96px) var(--vs-gutter);
  }
  .vs-stats-band__title {
    margin: 0 0 clamp(28px, 5cqi, 48px);
    font-size: 0.875rem;
    font-weight: 600;
    color: var(--vs-stats-muted);
  }
  .vs-stats-band__grid {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 32px 24px;
    margin: 0;
  }
  @container (min-width: 820px) {
    .vs-stats-band__grid {
      grid-template-columns: repeat(auto-fit, minmax(0, 1fr));
    }
  }
  .vs-stats-band__stat {
    display: flex;
    flex-direction: column;
    padding-left: 18px;
    border-left: var(--vs-border-w) solid var(--vs-stats-rule);
  }
  .vs-stats-band__value {
    order: -1;
    margin: 0;
    font-size: clamp(2.25rem, 5.5cqi, 4rem);
    line-height: 1;
    font-variant-numeric: tabular-nums;
  }
  .vs-stats-band__label {
    margin-top: 12px;
    font-size: 0.9375rem;
    font-weight: 600;
  }
  .vs-stats-band__note {
    margin: 4px 0 0;
    font-size: 0.8125rem;
    color: var(--vs-stats-muted);
  }
  .vs-stats-band__source {
    margin: clamp(28px, 5cqi, 48px) 0 0;
    font-size: 0.75rem;
    color: var(--vs-stats-muted);
  }
</style>
```
