Skip to main content
Compendium / Maturity & Process / Indicators / Practice Adoption Bar
#443

Practice Adoption Bar

Horizontal bar showing what fraction of DoCoDeGo practices the team has adopted — maturity by checklist.

STABLE DE
#gauge #real-content #dark-mode-tested #responsive
Live
// practices adopted 11/16
68%
remaining 5 practices
Spec

Intent

Stages compress; adoption percentages explain. This bar shows the count of practices live versus the canonical set, so a team can see exactly what's missing from the next rung.

Acceptance Criteria

  • [ ] Bar fills proportional to adopted / total
  • [ ] Numeric readout in tabular-nums
  • [ ] Bar uses pillar token, hollow remainder
  • [ ] Negative: does NOT round 99% up to 100%

Constraints

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

export const meta: CompendiumMeta = {
  id: 443,
  slug: 'practice-adoption-bar',
  name: 'Practice Adoption Bar',
  category: 'maturity-process',
  subcategory: 'indicators',
  pillar: 'de',
  description: 'Horizontal bar showing what fraction of DoCoDeGo practices the team has adopted — maturity by checklist.',
  spec: `## Intent
Stages compress; adoption percentages explain. This bar shows the count of practices live versus the canonical set, so a team can see exactly what's missing from the next rung.

## Acceptance Criteria
- [ ] Bar fills proportional to adopted / total
- [ ] Numeric readout in tabular-nums
- [ ] Bar uses pillar token, hollow remainder
- [ ] Negative: does NOT round 99% up to 100%

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

const adopted = 11;
const total = 16;
const pct = Math.floor((adopted / total) * 100);
---

<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">// practices adopted</span>
    <span class="font-mono text-[10px] uppercase tracking-widest tabular-nums">{adopted}/{total}</span>
  </header>
  <div class="p-3">
    <div class="relative h-6 border-4 border-black bg-paper overflow-hidden">
      <div class="h-full bg-de" style={`width: ${pct}%`} aria-hidden="true"></div>
      <div class="absolute inset-0 flex items-center justify-end pe-2">
        <span class="font-black text-[12px] tabular-nums">{pct}%</span>
      </div>
    </div>
    <div class="mt-3 grid grid-cols-4 gap-1.5" aria-hidden="true">
      {Array.from({ length: total }).map((_, i) => (
        <span class:list={['h-1.5 border-2 border-black', i < adopted ? 'bg-de' : 'bg-paper']}></span>
      ))}
    </div>
    <div class="mt-3 pt-3 border-t-2 border-black flex items-baseline justify-between font-mono text-[9px] uppercase tracking-widest">
      <span class="opacity-60">remaining</span>
      <span class="font-black tabular-nums">{total - adopted} practices</span>
    </div>
  </div>
</div>
</content>
</invoke>