Spec
Intent
A reusable, opinionated sparkline that other compositions can lean on. One stroke, no axes, no chrome — the trend is the message.
Acceptance Criteria
- [ ] Polyline traces a single series across the full width
- [ ] Auto-scales to min/max — no zero baseline
- [ ] Current value pinned at the end as a dot
- [ ] Negative: does NOT show gridlines or axis labels
Constraints
- Pure SVG, no JS
- Stroke uses var(--color-de)
// sparkline-mini.astro
---
import type { CompendiumMeta } from '../../../data/types';
export const meta: CompendiumMeta = {
id: 681,
slug: 'sparkline-mini',
name: 'Sparkline Mini',
category: 'metrics-telemetry',
subcategory: 'charts',
pillar: 'de',
description: 'Generic single-series sparkline primitive — the building block for any trend readout in the system.',
spec: `## Intent
A reusable, opinionated sparkline that other compositions can lean on. One stroke, no axes, no chrome — the trend is the message.
## Acceptance Criteria
- [ ] Polyline traces a single series across the full width
- [ ] Auto-scales to min/max — no zero baseline
- [ ] Current value pinned at the end as a dot
- [ ] Negative: does NOT show gridlines or axis labels
## Constraints
- Pure SVG, no JS
- Stroke uses var(--color-de)`,
tags: ['svg', 'chart', 'real-content', 'dark-mode-tested', 'responsive'],
status: 'stable',
health: { ics: 86, a11y: 'aa', themed: true, animated: false },
};
const series = [14, 18, 16, 22, 19, 25, 28, 24, 31, 29, 34, 38];
const min = Math.min(...series);
const max = Math.max(...series);
const range = max - min || 1;
const n = series.length - 1;
const xy = series.map((v, i) => ({ x: (i / n) * 100, y: 100 - ((v - min) / range) * 100 }));
const pts = xy.map((p) => `${p.x},${p.y}`).join(' ');
const last = xy.at(-1)!;
const current = series.at(-1)!;
---
<div data-this-component class="w-full bg-paper text-black border-4 border-black overflow-hidden">
<header class="flex items-baseline justify-between px-3 py-2 border-b-2 border-black">
<span class="font-mono text-[10px] uppercase tracking-widest opacity-60">// sparkline · 12 pts</span>
<span class="font-mono text-[10px] uppercase tracking-widest">SERIES</span>
</header>
<div class="grid grid-cols-[1fr_auto]">
<div class="p-3 border-e-2 border-black">
<svg viewBox="0 0 100 100" preserveAspectRatio="none" class="w-full h-20 block" aria-label={`Series trend, currently ${current}`}>
<polyline points={pts} fill="none" stroke="var(--color-de)" stroke-width="2.5" vector-effect="non-scaling-stroke" />
<circle cx={last.x} cy={last.y} r="3" fill="var(--color-de)" stroke="var(--color-ink)" stroke-width="0.6" vector-effect="non-scaling-stroke" />
</svg>
</div>
<div class="p-3 flex flex-col items-center justify-center min-w-[72px]">
<span class="font-black text-3xl tabular-nums leading-none">{current}</span>
<span class="font-mono text-[9px] uppercase tracking-widest opacity-60 mt-1">now</span>
</div>
</div>
</div>