Validates WCAG AA contrast ratios (minimum 4.5:1) for text and background color combinations in frontend code...
Validates text and background color combinations meet WCAG AA standards (4.5:1 minimum). Use before committing frontend changes or during code review.
Copy this checklist to track progress:
Contrast Validation Progress:
- [ ] Step 1: Identify files or components to check
- [ ] Step 2: Extract color combinations
- [ ] Step 3: Validate against approved combinations
- [ ] Step 4: Calculate ratios for unknown combinations
- [ ] Step 5: Generate violation report with fixes
For specific files: User provides file paths to check.
For recent UI changes:
git diff --name-only --diff-filter=AM 'frontend/src/**/*.tsx' 'frontend/src/**/*.jsx'
For specific component directories:
find frontend/src/components -name "*.tsx" -o -name "*.jsx"
Search for Tailwind color classes in pattern bg-{color}.*text-{color}:
grep -oE "(bg-[a-z-]+|text-[a-z-]+)" [file_path] | sort | uniq
Look for combinations where background and text colors appear together:
# className with both bg- and text-
grep -n 'className=.*bg-.*text-' [file_path]
# Nested elements (parent bg, child text)
grep -A2 -B2 'bg-[a-z-]+' [file_path] | grep 'text-[a-z-]+'
Extract combinations:
bg-scorecard text-charcoalbg-fairway text-scorecardbg-turf text-scorecardbg-coral text-scorecard--fairway: #1B4332 /* Deep forest green */
--turf: #2D6A4F /* Medium green */
--rough: #95D5B2 /* Light sage */
--coral: #FF9F1C /* Orange */
--flag: #EF476F /* Red */
--sky: #118AB2 /* Blue */
--scorecard: #F8F9FA /* Off-white */
--charcoal: #1C1C1E /* Dark gray */
--soft-grey: #CED4DA /* Light gray */
These combinations PASS and are preferred:
"bg-scorecard text-charcoal" // 16.75:1 ✅ Excellent
"bg-fairway text-scorecard" // 13.94:1 ✅ Excellent
"bg-turf text-scorecard" // 9.2:1 ✅ Excellent
"bg-charcoal text-scorecard" // 16.75:1 ✅ Excellent
"bg-flag text-scorecard" // 4.9:1 ✅ Good
"bg-coral text-scorecard" // 4.9:1 ✅ Good
"bg-sky text-scorecard" // 5.8:1 ✅ Good
These combinations PASS minimum standards:
"bg-scorecard text-turf" // 4.5:1 ✅ Acceptable
"bg-rough text-charcoal" // 4.2:1 ⚠️ Marginal (use with caution)
"bg-soft-grey text-charcoal" // 8.9:1 ✅ Good
These combinations FAIL and must not be used:
"bg-scorecard text-scorecard" // 1.05:1 ❌ Invisible
"bg-scorecard text-rough" // 1.8:1 ❌ Poor contrast
"bg-scorecard text-soft-grey" // 1.9:1 ❌ Poor contrast
"bg-fairway text-charcoal" // 1.2:1 ❌ Poor contrast
"bg-fairway text-turf" // 1.5:1 ❌ Poor contrast
"bg-turf text-fairway" // 1.5:1 ❌ Poor contrast
"bg-rough text-scorecard" // 1.8:1 ❌ Poor contrast
"bg-rough text-soft-grey" // 1.05:1 ❌ Invisible
"bg-coral text-charcoal" // 3.4:1 ❌ Below WCAG AA
"bg-flag text-charcoal" // 3.8:1 ❌ Below WCAG AA
"bg-sky text-charcoal" // 2.9:1 ❌ Below WCAG AA
If you encounter a combination not in the approved list:
Formula:
Contrast Ratio = (L1 + 0.05) / (L2 + 0.05)
Where L1 is relative luminance of the lighter color, L2 is relative luminance of the darker color.
WCAG Standards:
If uncertain about a custom color or opacity combination:
Use WebContrastChecker tool or similar:
1. Input background hex color
2. Input text hex color
3. Check if ratio >= 4.5:1 for WCAG AA compliance
For TapScore brand colors, always reference the approved list first.
Create structured report:
## Contrast Ratio Violations Report
### File: [file_path]
**Total Violations:** [count]
---
#### Line [X]: FAIL - `bg-scorecard text-rough`
**Current:**
```tsx
<div className="bg-scorecard text-rough">
Low contrast text
</div>
Issue: Contrast ratio 1.8:1 fails WCAG AA (needs 4.5:1 minimum)
Fix Option 1 (Recommended):
<div className="bg-scorecard text-charcoal">
Accessible text
</div>
Contrast ratio: 16.75:1 ✅ WCAG AAA
Fix Option 2:
<div className="bg-scorecard text-turf">
Accessible text
</div>
Contrast ratio: 4.5:1 ✅ WCAG AA
bg-coral text-charcoalCurrent:
<Button className="bg-coral text-charcoal">
Click Me
</Button>
Issue: Contrast ratio 3.4:1 fails WCAG AA
Fix (Use approved combination):
<Button className="bg-coral text-scorecard">
Click Me
</Button>
Contrast ratio: 4.9:1 ✅ WCAG AA
Approval needed: Should I apply these fixes now?
---
## Common Violation Patterns
### Pattern 1: Light on Light
**Violation:**
```tsx
<div className="bg-scorecard text-soft-grey">
Invisible text
</div>
Fix:
<div className="bg-scorecard text-charcoal">
Visible text
</div>
Why: Light gray on off-white has insufficient contrast.
Violation:
<div className="bg-fairway text-charcoal">
Hard to read
</div>
Fix:
<div className="bg-fairway text-scorecard">
Easy to read
</div>
Why: Dark green on dark gray fails contrast requirements.
Violation:
<div className="bg-fairway text-turf">
Blends together
</div>
Fix:
<div className="bg-fairway text-scorecard">
Clear contrast
</div>
Why: Two greens of similar luminance fail contrast.
Violation:
<div className="bg-scorecard text-charcoal/50">
Faded text
</div>
Issue: Opacity reduces contrast ratio. charcoal/50 may fail WCAG AA.
Fix:
<div className="bg-scorecard text-charcoal/70">
Better contrast
</div>
Or better:
<div className="bg-scorecard text-charcoal">
Full contrast
</div>
Rule: Avoid opacity on text unless absolutely necessary. If used, verify contrast ratio.
Hover states should also meet WCAG AA:
Bad:
className="bg-scorecard text-charcoal hover:bg-rough hover:text-scorecard"
Issue: bg-rough text-scorecard fails contrast (1.8:1).
Good:
className="bg-scorecard text-charcoal hover:bg-turf/5"
Why: Keep text color unchanged, use subtle background tint.
Success indicators:
// ✅ Good
<span className="text-turf">Success</span>
// ❌ Bad
<span className="bg-scorecard text-rough">Success</span>
Error indicators:
// ✅ Good
<span className="text-flag">Error</span>
// ✅ Good (with background)
<span className="bg-flag text-scorecard">Error</span>
Always use solid backgrounds with approved contrasts:
Good:
<Badge className="bg-turf text-scorecard">Active</Badge>
<Badge className="bg-coral text-scorecard">Pending</Badge>
<Badge className="bg-flag text-scorecard">Error</Badge>
Bad:
<Badge className="bg-rough text-scorecard">Active</Badge> {/* Fails */}
<Badge className="bg-scorecard text-rough">Active</Badge> {/* Fails */}
Check all files for common violations:
# Check for prohibited combinations
for file in $(find frontend/src -name "*.tsx"); do
echo "=== $file ==="
# Check for known bad combinations
if grep -q "bg-scorecard.*text-rough\|bg-rough.*text-scorecard" "$file"; then
echo "❌ FAIL: bg-scorecard + text-rough detected"
grep -n "bg-scorecard.*text-rough\|bg-rough.*text-scorecard" "$file"
fi
if grep -q "bg-fairway.*text-charcoal\|bg-fairway.*text-turf" "$file"; then
echo "❌ FAIL: bg-fairway + dark text detected"
grep -n "bg-fairway.*text-charcoal\|bg-fairway.*text-turf" "$file"
fi
if grep -q "bg-coral.*text-charcoal" "$file"; then
echo "❌ FAIL: bg-coral + text-charcoal detected"
grep -n "bg-coral.*text-charcoal" "$file"
fi
echo ""
done
After generating report:
For complete reference, see docs/STYLE_GUIDE.md sections:
Quick reminder:
text-scorecard (off-white)text-charcoal (dark gray)text-scorecard unless otherwise approvedContrast validation ensures:
Run validation before committing any UI changes with text/background color combinations.