Skip to main content
Compendium / Metrics & Telemetry / Charts / Bar Mini
#683

Bar Mini

Vertical bar mini chart — discrete buckets across time, no axes, no chrome.

STABLE DE
#svg #chart #real-content #dark-mode-tested #responsive
Live
// per period · 12 BARS
16 now
Spec

Intent

For countable, discrete events per period (deploys, drift incidents, releases) a bar chart reads more honestly than a line. Each bar is a period; the height is the count.

Acceptance Criteria

  • [ ] One vertical bar per period
  • [ ] Bars scaled to the largest period in the window
  • [ ] Current period highlighted distinctly
  • [ ] Negative: does NOT interpolate between periods

Constraints

  • Pure SVG, no JS
  • Tabular-nums readout
// bar-mini.astro
---
import type { CompendiumMeta } from '../../../data/types';

export const meta: CompendiumMeta = {
  id: 683,
  slug: 'bar-mini',
  name: 'Bar Mini',
  category: 'metrics-telemetry',
  subcategory: 'charts',
  pillar: 'de',
  description: 'Vertical bar mini chart — discrete buckets across time, no axes, no chrome.',
  spec: `## Intent
For countable, discrete events per period (deploys, drift incidents, releases) a bar chart reads more honestly than a line. Each bar is a period; the height is the count.

## Acceptance Criteria
- [ ] One vertical bar per period
- [ ] Bars scaled to the largest period in the window
- [ ] Current period highlighted distinctly
- [ ] Negative: does NOT interpolate between periods

## Constraints
- Pure SVG, no JS
- Tabular-nums readout`,
  tags: ['svg', 'chart', 'real-content', 'dark-mode-tested', 'responsive'],
  status: 'stable',
  health: { ics: 87, a11y: 'aa', themed: true, animated: false },
};

const series = [4, 6, 5, 9, 7, 11, 8, 12, 10, 14, 11, 16];
const max = Math.max(...series);
const n = series.length;
const barW = 100 / n;
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">// per period · 12</span>
    <span class="font-mono text-[10px] uppercase tracking-widest">BARS</span>
  </header>
  <div class="grid grid-cols-[1fr_auto]">
    <div class="p-3 border-e-2 border-black">
      <svg viewBox="0 0 100 60" preserveAspectRatio="none" class="w-full h-20 block" aria-label={`Bar series, currently ${current}`}>
        {series.map((v, i) => {
          const h = (v / max) * 56;
          const isLast = i === n - 1;
          return (
            <rect
              x={i * barW + 0.6}
              y={58 - h}
              width={barW - 1.2}
              height={h}
              fill={isLast ? 'var(--color-de)' : 'var(--color-ink)'}
              opacity={isLast ? '1' : '0.55'}
            />
          );
        })}
        <line x1="0" y1="58" x2="100" y2="58" stroke="var(--color-ink)" stroke-width="1" 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>