Complete guide to using the UI Consistency Guard system for maintaining design system integrity.
The UI Consistency Guard is a three-tier system that ensures design token compliance and prevents style drift across your codebase. It detects:
- Token drift - Hardcoded colors, spacing, and other values that should use design tokens
- Style duplication - Repeated CSS patterns that should be consolidated
- Component duplication - Similar components across frameworks (React, Vue, Svelte)
- CSS smells - Specificity escalation,
!importantoveruse, and other anti-patterns - Role inconsistencies - Outlier styling for similar UI elements (buttons, inputs, cards)
Target latency: <300ms p95
Fast feedback during development. Runs automatically on each commit to catch issues before they enter the codebase.
# Runs automatically via pre-commit hook
# Or manually:
claude-indexer ui-guard src/components/Button.tsxWhat it checks:
- Token drift in changed files
- New
!importantdeclarations - Obvious duplicates within the changeset
Target latency: <10 minutes for 1000+ file repos
Comprehensive analysis during pull requests. Performs cross-file duplicate detection and generates detailed reports.
# Run full CI audit
claude-indexer quality-gates run ui --format sarif -o results.sarif
# Run with verbose output
claude-indexer quality-gates run ui --verboseWhat it checks:
- All Tier 0 checks across entire codebase
- Cross-file style duplicate detection
- Component similarity clustering
- Role-based outlier detection
- Baseline vs new issue separation
Target latency: <5 minutes for focused audit
On-demand design critique with actionable recommendations. Used when planning refactoring or design system updates.
# Full design audit
claude-indexer redesign
# Focus on specific area
claude-indexer redesign --focus "button components"
# Include runtime analysis (requires Playwright)
claude-indexer redesign --with-runtimeWhat it provides:
- Evidence-backed design critique
- Consolidated recommendations
- Priority-ranked cleanup plan
- Visual diff when using runtime mode
These rules detect hardcoded values that should use design tokens.
Severity: FAIL
Detects hardcoded colors that should use CSS custom properties.
// BAD - triggers COLOR.NON_TOKEN
const styles = {
backgroundColor: '#3b82f6',
color: 'white',
};
// GOOD - uses design tokens
const styles = {
backgroundColor: 'var(--color-primary-600)',
color: 'var(--color-text-inverse)',
};Severity: FAIL
Detects spacing values not on your design scale.
/* BAD - off-scale spacing */
.container {
padding: 13px; /* Not on 4px/8px scale */
margin: 7px;
}
/* GOOD - on-scale spacing */
.container {
padding: var(--spacing-3); /* 12px */
margin: var(--spacing-2); /* 8px */
}Severity: FAIL
Detects border-radius values not matching your token scale.
/* BAD - arbitrary radius */
.card {
border-radius: 5px;
}
/* GOOD - token-based radius */
.card {
border-radius: var(--radius-md);
}Severity: FAIL
Detects font sizes, weights, or line heights outside your type scale.
/* BAD - arbitrary typography */
.heading {
font-size: 19px;
font-weight: 550;
}
/* GOOD - type scale values */
.heading {
font-size: var(--font-size-xl);
font-weight: var(--font-weight-semibold);
}These rules detect repeated patterns that should be consolidated.
Severity: WARN
Detects identical CSS property sets across files.
// File: Button.tsx
const buttonStyles = {
padding: '8px 16px',
borderRadius: '4px',
fontWeight: 600,
};
// File: Card.tsx - DUPLICATE detected
const cardButtonStyles = {
padding: '8px 16px',
borderRadius: '4px',
fontWeight: 600,
};
// RECOMMENDATION: Extract to shared utility
// src/styles/button-base.cssSeverity: WARN
Detects style sets with >85% similarity but slight variations.
// Button.tsx
const primary = { padding: '8px 16px', background: 'blue' };
// SubmitButton.tsx - NEAR_DUPLICATE (only background differs)
const submit = { padding: '8px 16px', background: 'green' };
// RECOMMENDATION: Use variant pattern insteadSeverity: WARN
Detects repeated Tailwind/utility class sequences.
<!-- Multiple files have this exact sequence -->
<div class="flex items-center justify-between px-4 py-2 bg-white rounded-lg shadow-sm">
<!-- RECOMMENDATION: Extract to component or @apply directive -->Severity: WARN
Detects similar component structures across your codebase.
Duplicate cluster detected:
- src/components/Button.tsx
- src/components/ButtonVariant.tsx
- src/components/VueButton.vue
Similarity: 87%
RECOMMENDATION: Consolidate into single component with variants
These rules detect problematic CSS patterns.
Severity: WARN
Detects selectors with excessive specificity.
/* BAD - specificity escalation */
.app .main .content .card .card-header .title {
color: red;
}
body #root .container > .item[data-active="true"]:not(.disabled) {
background: blue;
}
/* GOOD - flat, low-specificity selectors */
.card-title {
color: var(--color-text-primary);
}
.item--active {
background: var(--color-bg-active);
}Severity: FAIL
Detects new !important declarations (baseline declarations are exempted).
/* BAD - new !important usage */
.button {
background: blue !important; /* FAIL: New !important */
}
/* If !important is truly necessary, document why: */
/* ui-suppress: legacy-override - overrides third-party styles */
.button {
background: blue !important;
}Severity: WARN
Detects suppression comments without explanation.
/* BAD - no rationale */
/* ui-suppress */
.override { color: red !important; }
/* GOOD - includes rationale */
/* ui-suppress: vendor-override - Material UI specificity conflict */
.override { color: red !important; }These rules detect outlier styling for similar UI roles.
Severity: WARN
Detects buttons with styling that deviates significantly from the norm.
Role outlier detected: src/components/SpecialButton.tsx
- padding: 4px (norm: 8-16px)
- border-radius: 0px (norm: 4-8px)
Consider aligning with design system button styles.
Severity: WARN
Detects input fields with inconsistent styling.
Severity: WARN
Detects card components with outlier styling.
Severity: WARN
Detects inconsistent focus ring styling across interactive elements.
/* Inconsistent focus rings detected */
.button-a:focus { outline: 2px solid blue; }
.button-b:focus { box-shadow: 0 0 0 2px blue; }
.button-c:focus { outline: none; } /* Accessibility concern */
/* RECOMMENDATION: Use consistent focus utility */
.focus-ring:focus {
outline: var(--focus-ring-width) solid var(--focus-ring-color);
outline-offset: var(--focus-ring-offset);
}Create .ui-quality.yaml in your project root:
# Token sources
tokens:
css_vars:
paths:
- src/styles/tokens.css
- src/styles/colors.css
# Files to scan
scanning:
paths:
- src/**/*.tsx
- src/**/*.css
- src/**/*.scss
exclude:
- node_modules
- dist
- "**/*.test.tsx"
# Gating behavior
gating:
mode: strict # 'strict' or 'lenient'tokens:
# CSS custom properties
css_vars:
paths:
- src/styles/tokens.css
prefixes:
- --color-
- --spacing-
- --radius-
- --font-
- --shadow-
# Tailwind integration
tailwind:
config_path: tailwind.config.js
# Figma integration (optional)
figma:
file_key: ${FIGMA_FILE_KEY}
access_token: ${FIGMA_ACCESS_TOKEN}
scanning:
paths:
- src/**/*.tsx
- src/**/*.jsx
- src/**/*.vue
- src/**/*.svelte
- src/**/*.css
- src/**/*.scss
exclude:
- node_modules
- dist
- coverage
- "**/*.stories.tsx"
- "**/*.test.tsx"
gating:
mode: strict
similarity_thresholds:
duplicate: 0.95 # Exact duplicates
near_duplicate: 0.85 # Similar patterns
outlier: 1.5 # Standard deviations for outlier detection
min_confidence: 0.7
# Rule customization
rules:
COLOR.NON_TOKEN:
enabled: true
severity: FAIL
STYLE.DUPLICATE_SET:
enabled: true
severity: WARN
min_occurrences: 3 # Only flag if 3+ duplicates
IMPORTANT.NEW_USAGE:
enabled: true
severity: FAIL
# Baseline configuration
baseline:
path: .ui-quality/baseline.json
auto_update: falseTo suppress specific findings with justification:
// Single-line suppression
// ui-suppress: COLOR.NON_TOKEN - brand color not in token system
const brandColor = '#FF6B35';
// Block suppression
/* ui-suppress-start: STYLE.DUPLICATE_SET - intentional variant styles */
const variantA = { padding: '8px' };
const variantB = { padding: '8px' };
/* ui-suppress-end *//* CSS suppression */
/* ui-suppress: CSS.SPECIFICITY.ESCALATION - overriding third-party library */
.mui-override .MuiButton-root {
background: var(--color-primary-600);
}- Start with a baseline: Run
claude-indexer quality-gates baseline updateto establish current state - Focus on new issues: Baseline issues won't block CI
- Incremental cleanup: Use the cleanup map to prioritize fixes
- Adjust thresholds: Lower
similarity_thresholdsin config - Use suppressions: Document intentional patterns with
ui-suppress - Exclude files: Add test/story files to exclude list
- Enable caching: Default on, stored in
.ui-quality/cache/ - Limit scope: Use
scanning.pathsto focus on source files - Incremental mode: Only analyze changed files in PRs
- Check paths: Ensure token file paths are correct
- Verify format: CSS custom properties must use
--prefix - Check prefixes: Configure
tokens.css_vars.prefixesif using non-standard naming
-
Phase 1: Observation
- Run audit without blocking CI
- Establish baseline
- Review cleanup map
-
Phase 2: Prevention
- Enable pre-commit guard
- Block new violations in CI
- Baseline protects legacy code
-
Phase 3: Cleanup
- Work through cleanup map P1 items
- Gradually reduce baseline
- Track progress over time
- Token-first: Define tokens before components
- Document tokens: Keep token documentation current
- Enforce early: Add UI guard to new projects from start
- Review regularly: Run
/redesignquarterly
- Pre-commit guard: Catches 80% of issues instantly
- CI audit: Comprehensive check on PRs
- Design reviews: Use
/redesignoutput in design discussions - Cleanup sprints: Dedicated time to reduce baseline
# .pre-commit-config.yaml
repos:
- repo: local
hooks:
- id: ui-guard
name: UI Consistency Guard
entry: claude-indexer ui-guard
language: system
files: \.(tsx|jsx|vue|svelte|css|scss)$
pass_filenames: trueSee UI CI Setup Guide for detailed GitHub Actions configuration.
The UI Guard integrates with VS Code through the SARIF Viewer extension:
- Install "SARIF Viewer" extension
- Run audit with SARIF output
- View findings inline in editor
| Operation | Target | Typical |
|---|---|---|
| Single file (Tier 0) | <100ms | 50-80ms |
| Batch 10 files (Tier 0) | <300ms | 150-250ms |
| Full repo 100 files (Tier 1) | <60s | 30-45s |
| Full repo 1000 files (Tier 1) | <10min | 5-8min |
| Focused audit (Tier 2) | <5min | 2-3min |
- Cold cache: Full analysis time
- Warm cache: 50-70% faster on subsequent runs
- Incremental mode: Only changed files analyzed
- UI CI Setup Guide - CI/CD integration details
- UI Tool TDD - Technical design document
- UI Tool PRD - Product requirements
- UI Development Roadmap - Implementation phases