Skip to main content
Compendium / Maturity & Process / Indicators / Stage Pip
#441

Stage Pip

Tiny four-pip indicator — one filled dot per completed maturity stage, the smallest possible readout.

STABLE DE
#badge #real-content #dark-mode-tested #responsive
Live
// stage pip
stage
2/4
inline · header strip · ticket margin
Spec

Intent

The most compact possible maturity readout. Four pips, one filled per stage reached. Fits inline next to a team name or in a sidebar header without taking a card-sized slot.

Acceptance Criteria

  • [ ] Four pips arranged horizontally
  • [ ] Pips below current stage filled with pillar token
  • [ ] Pips at/above current stage hollow
  • [ ] Negative: does NOT label stages (label belongs elsewhere)

Constraints

  • Pure CSS
  • Theme-aware via tokens
// stage-pip.astro
---
import type { CompendiumMeta } from '../../../data/types';

export const meta: CompendiumMeta = {
  id: 441,
  slug: 'stage-pip',
  name: 'Stage Pip',
  category: 'maturity-process',
  subcategory: 'indicators',
  pillar: 'de',
  description: 'Tiny four-pip indicator — one filled dot per completed maturity stage, the smallest possible readout.',
  spec: `## Intent
The most compact possible maturity readout. Four pips, one filled per stage reached. Fits inline next to a team name or in a sidebar header without taking a card-sized slot.

## Acceptance Criteria
- [ ] Four pips arranged horizontally
- [ ] Pips below current stage filled with pillar token
- [ ] Pips at/above current stage hollow
- [ ] Negative: does NOT label stages (label belongs elsewhere)

## Constraints
- Pure CSS
- Theme-aware via tokens`,
  tags: ['badge', 'real-content', 'dark-mode-tested', 'responsive'],
  status: 'stable',
  health: { ics: 88, a11y: 'aa', themed: true, animated: false },
};

const stage = 2;
const total = 4;
---

<div data-this-component class="w-full bg-paper text-black border-4 border-black p-4 overflow-hidden">
  <div class="font-mono text-[10px] uppercase tracking-widest opacity-60 mb-3">// stage pip</div>
  <div class="flex items-center gap-2">
    <span class="font-mono text-[10px] uppercase tracking-widest opacity-60 shrink-0">stage</span>
    <ol class="flex items-center gap-1.5" aria-label={`Stage ${stage} of ${total}`}>
      {Array.from({ length: total }).map((_, i) => (
        <li
          class:list={[
            'w-3 h-3 border-2 border-black',
            i < stage ? 'bg-de' : 'bg-paper',
          ]}
          aria-current={i + 1 === stage ? 'step' : undefined}
        ></li>
      ))}
    </ol>
    <span class="font-mono text-[10px] uppercase tracking-widest font-black tabular-nums ms-auto">{stage}/{total}</span>
  </div>
  <div class="mt-3 pt-3 border-t-2 border-black font-mono text-[9px] uppercase tracking-widest opacity-60">
    inline · header strip · ticket margin
  </div>
</div>
</content>
</invoke>