---
name: design-system-drift
description: "Measure design system decay in a frontend codebase with five quantified metrics: hardcoded colors, component reinvention, token adoption, context provider bloat, accessibility gap. Use when auditing UI consistency, sizing a refactor, or proving drift with numbers. Not for merging multiple audits into one roadmap: use cross-domain-audit-synthesis. Not for building new marketing pages: use awwwards-2026."
license: MIT
metadata:
  author: TechTide AI (Alex Cinovoj)
  provenance: original
  category: Quality & Security
---

# Design System Drift

Quantify how far a frontend has drifted from its design system. Five metrics, each with a command or formula and a threshold, so the audit ends in numbers, not adjectives.

## Metric 1: Hardcoded color census

```bash
grep -rn '#[0-9a-fA-F]\{3,8\}' src/ --include='*.tsx' --include='*.css' | grep -v node_modules | wc -l
grep -roh '#[0-9a-fA-F]\{3,8\}' src/ --include='*.tsx' --include='*.css' | sort -u | wc -l
```

First number is total occurrences, second is unique colors. Under 50 = Healthy. 50-200 = Moderate. 200-500 = Significant. Over 500 = Failed.

## Metric 2: Component reinvention ratio

Count custom implementations vs library usages per category: modals, buttons, dropdowns, tooltips, toasts, form inputs.

Formula: `reinventions / (reinventions + library_usages) * 100`.

Under 20% = Healthy. 20-50% = Mixed. 50-80% = Library ignored. Over 80% = Library decorative.

## Metric 3: Token adoption rate

```bash
grep -rn 'var(--' src/ --include='*.tsx' --include='*.css' | wc -l   # token usage
grep -rn 'style={{' src/ --include='*.tsx' | wc -l                   # raw inline values
```

Formula: `token_usages / (token_usages + raw_values) * 100`.

Over 80% = Healthy. 50-80% = Moderate. Under 50% = Token system decorative.

## Metric 4: Context provider bloat

```bash
grep -rn 'createContext\|React.createContext' src/ | wc -l
find src/ -name '*Context*' -o -name '*Provider*' | xargs wc -l | sort -rn | head -20
```

Under 10 contexts = Normal. 10-20 = Heavy. Over 20 = Context soup. Any single context file over 500 lines: decompose immediately.

## Metric 5: Accessibility gap from reinvention

```bash
grep -rn 'aria-' src/components/ --include='*.tsx' | wc -l
grep -rn 'role=' src/components/ --include='*.tsx' | wc -l
grep -rn 'tabIndex\|onKeyDown' src/components/ --include='*.tsx' | wc -l
```

Every reinvented component without these attributes is debt the library would have handled for free. Read this metric together with Metric 2: high reinvention plus low aria counts is compounding a11y debt.

## Output format

| Metric | Current | Target | Gap | Priority |
|---|---|---|---|---|
| Hardcoded colors | N | <50 | N-50 | HIGH if >200 |
| Reinvention ratio | N% | <20% | N-20% | HIGH if >50% |
| Token adoption | N% | >80% | 80-N% | MEDIUM |
| Context count | N | <10 | N-10 | MEDIUM if >15 |
| A11y coverage | N attrs | Baseline | Gap | HIGH if reinvention >50% |

## Good vs bad

Bad conclusion: "The codebase has drifted quite a bit from the design system and could use cleanup."

Good conclusion: "312 hardcoded colors (41 unique), reinvention 64%, token adoption 38%. Verdict: library is decorative. Priority: consolidate colors to tokens (HIGH), replace the 6 custom modals (HIGH)."

## Verification

Run all five metric commands from the repo root. Expect each to return a number, and the report table to contain no empty cells and no adjectives in place of values. If a grep returns 0 unexpectedly, check the source layout first (a `src/` that is actually `app/` or `.jsx` instead of `.tsx`) and adjust the globs before trusting the zero.

Spot-check Metric 2: open 3 files counted as reinventions. Expect each to actually reimplement a library component, not wrap it. Wrappers that delegate to the library count as library usage, reclassify them.

## Completion checklist

- [ ] All five metrics computed with commands or counts shown
- [ ] Grep globs adjusted to the project's real file layout
- [ ] Reinvention counts spot-checked against 3 real files
- [ ] Output table complete with gap and priority per metric
- [ ] Every HIGH priority tied to a threshold breach, not opinion

Any box unchecked: not done. Fix or say so.

## Footguns

- **Counting wrappers as reinventions.** Inflates Metric 2 and points the refactor at healthy code. Fix: a wrapper that renders the library component is a library usage.
- **Trusting zeros from wrong globs.** A Vue or `.jsx` codebase greps clean on `*.tsx` and looks healthy. Fix: confirm file extensions and roots before running the census.
- **Reporting only totals for colors.** 500 occurrences of 6 tokens-to-be is a different problem than 500 unique hexes. Fix: always report both counts.
- **Turning thresholds into goals mid-audit.** Adjusting the threshold to make the number green defeats the audit. Fix: thresholds are fixed, report the breach.
