Skip to main content
Compendium / Pillars & Roles / Loops & Cycles / DO → CO → DE Phase Pip
#384

DO → CO → DE Phase Pip

A three-dot progression pip showing which phase — Document, Construct, Deliver — a workstream is currently in.

STABLE GO
#svg #real-content #dark-mode-tested #responsive
Live
// phase CO
DO CO DE
Spec

Intent

A workstream always lives in one of three execution phases. This pip is a tiny status marker — three dots, one filled — that fits in a row label or sidebar.

Acceptance Criteria

  • [ ] Three dots labelled DO / CO / DE
  • [ ] Current dot uses its pillar token; completed are ink-filled; future are outlined
  • [ ] Connecting hairlines convey direction
  • [ ] Negative: does NOT require JS

Constraints

  • Pure SVG
  • Theme-aware via tokens
// do-co-de-phase-pip.astro
---
import type { CompendiumMeta } from '../../../data/types';

export const meta: CompendiumMeta = {
  id: 384,
  slug: 'do-co-de-phase-pip',
  name: 'DO → CO → DE Phase Pip',
  category: 'pillars-roles',
  subcategory: 'loops-cycles',
  pillar: 'go',
  description: 'A three-dot progression pip showing which phase — Document, Construct, Deliver — a workstream is currently in.',
  spec: `## Intent
A workstream always lives in one of three execution phases. This pip is a tiny status marker — three dots, one filled — that fits in a row label or sidebar.

## Acceptance Criteria
- [ ] Three dots labelled DO / CO / DE
- [ ] Current dot uses its pillar token; completed are ink-filled; future are outlined
- [ ] Connecting hairlines convey direction
- [ ] Negative: does NOT require JS

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

const phases = [
  { k: 'DO', c: 'var(--color-do)' },
  { k: 'CO', c: 'var(--color-co)' },
  { k: 'DE', c: 'var(--color-de)' },
];
const activeIdx = 1;
---

<div data-this-component class="w-full bg-paper text-black border-4 border-black p-3 overflow-hidden">
  <div class="flex items-baseline justify-between mb-2 gap-2">
    <span class="font-mono text-[10px] uppercase tracking-widest opacity-60">// phase</span>
    <span class="font-mono text-[10px] uppercase tracking-widest">{phases[activeIdx].k}</span>
  </div>
  <svg viewBox="0 0 200 50" class="w-full block" aria-label={`Phase pip, currently ${phases[activeIdx].k}`} role="img">
    <line x1="30" y1="22" x2="170" y2="22" stroke="var(--color-ink)" stroke-width="2" vector-effect="non-scaling-stroke" />
    {phases.map((p, i) => {
      const cx = 30 + i * 70;
      const done = i < activeIdx;
      const active = i === activeIdx;
      const fill = active ? p.c : done ? 'var(--color-ink)' : 'var(--color-paper)';
      return (
        <g>
          <circle cx={cx} cy="22" r="9" fill={fill} stroke="var(--color-ink)" stroke-width="3" />
          <text x={cx} y="44" text-anchor="middle" font-family="JetBrains Mono, monospace" font-size="9" font-weight="700" letter-spacing="1.5" fill="var(--color-ink)" opacity={active ? 1 : 0.55}>{p.k}</text>
        </g>
      );
    })}
  </svg>
</div>