Audit and fix icon and illustration anti-patterns across the codebase.
Target: $ARGUMENTS
If no target is provided, scan src/components/ and src/app/(public)/.
Before Starting
- Read
src/app/globals.cssto confirm the current semantic color token inventory. - Read
src/components/ui/icon.tsxif it exists — this is the canonical Icon wrapper. If it doesn't exist, note it as a critical gap. - Check which icon libraries are installed:
grep -r "from 'lucide-react'\|from '@heroicons\|from 'react-icons\|from 'phosphor" package.json
Scan Checklist
1. MIXED ICON LIBRARIES (Critical)
This codebase uses Lucide React only. Any other icon library is a violation.
Search for:
from '@heroicons/react'from 'react-icons'from 'phosphor-react'from '@radix-ui/react-icons'— allowed ONLY insidesrc/components/ui/*(shadcn internals)from 'feather-icons'- Any
<svg>with inline path data that duplicates a Lucide icon
Fix: Replace with the equivalent Lucide icon. Map using the Lucide icon search at lucide.dev.
2. RAW LUCIDE USAGE (High)
Icons should always be used via the canonical <Icon> wrapper (src/components/ui/icon.tsx), not imported and rendered directly. Raw usage bypasses the size scale, accessibility defaults, and flex-compression guard.
Search for patterns like:
import { ArrowRight, Check, X } from 'lucide-react'
// then used as: <ArrowRight className="w-4 h-4" />
Allowed exception: Inside src/components/ui/* (shadcn primitives) and the Icon wrapper itself.
Fix: Replace <IconName className="w-N h-N" /> with <Icon icon={IconName} size="sm" />.
3. ARBITRARY ICON SIZES (High)
Icons must use the canonical size token scale, not arbitrary pixel values:
| Token | Size | Use case |
|---|---|---|
xs |
12px | Captions, badges, inline metadata |
sm |
16px | Inline text, form labels, table cells |
md |
20px | Default UI, buttons, nav items |
lg |
24px | Section headers, card actions, prominent UI |
xl |
32px | Empty states, feature highlights |
2xl |
48px | Hero sections, marketing, onboarding |
Search for:
w-[orh-[with pixel values applied to icon elementsw-3 h-3,w-5 h-5,w-6 h-6,w-7 h-7,w-8 h-8,w-10 h-10— these bypass the token scalesize={with numeric values other than 12, 16, 20, 24, 32, 48
Fix: Replace with the <Icon size="md"> pattern.
4. HARDCODED ICON COLORS (High)
Icons must inherit their color from the surrounding text context via currentColor. Never set a specific color on an icon.
Search for:
text-blue-*,text-gray-*,text-red-*etc. on icon elements (should be semantic:text-muted-foreground,text-primary,text-destructive)fill="orstroke="with hex values or named colors (notcurrentColor) in inline SVGscolor=prop on Lucide icons
Fix: Remove the color class from the icon; apply it to the parent container using semantic tokens instead. Or, if only the icon needs color, use text-primary, text-muted-foreground, text-destructive.
5. MISSING FLEX-COMPRESSION GUARD (Medium)
Icons inside flex or grid containers will compress if shrink-0 is missing.
Search for icon elements (or <Icon> wrapper usages) inside:
flexcontainers withoutshrink-0on the iconitems-centerrows where the icon is a sibling of text
Fix: Add shrink-0 to the icon's className (the <Icon> wrapper applies this automatically when used correctly).
6. ACCESSIBILITY VIOLATIONS (High)
Pattern 1 — Decorative icons (no meaning without adjacent text):
// ✅ Correct
<Icon icon={Check} size="md" aria-hidden />
<span>Saved</span>
// ❌ Wrong — icon has no label, no aria-hidden
<CheckIcon className="w-5 h-5" />
<span>Saved</span>
Pattern 2 — Icon-only buttons (icon IS the only affordance):
// ✅ Correct
<Button variant="ghost" size="icon" aria-label="Close dialog">
<Icon icon={X} size="md" aria-hidden />
</Button>
// ❌ Wrong — no label, screen reader reads nothing useful
<button
<XIcon className="w-5 h-5" />
</button>
Pattern 3 — Standalone meaningful icons (rare — chart markers, status indicators):
// ✅ Correct
<Icon icon={AlertTriangle} size="md" label="Warning" />
// Or for SVG illustrations:
<svg role="img" aria-label="Empty inbox illustration">
<title>Empty inbox illustration</title>
...
</svg>
Search for:
- Icon-only
<button>elements withoutaria-label <Button size="icon">withoutaria-label- Icon elements that are the sole content of a clickable element, with no accessible label
7. ILLUSTRATION ANTI-PATTERNS (Medium)
Illustrations are larger SVGs used for empty states, onboarding, marketing sections, and feature highlights. They follow different rules from icons.
Search for:
<img src="*.png">or<img src="*.jpg">used for illustrations (should be SVG)- Inline SVG without
role="img"and<title>(if it conveys meaning) - SVG files that embed hardcoded hex colors (should use CSS custom properties to inherit theme)
- Illustrations that don't have a dark-mode variant or don't use
currentColor/CSS vars <img>elements with empty or missingaltattribute- Raster PNGs in
public/images/illustrations/that could be SVG
Fix per case:
- Replace PNG illustrations with SVG equivalents
- Add
role="img"+<title>to meaningful inline SVGs - For decorative illustrations:
aria-hidden="true"oralt="" - Refactor hardcoded SVG colors to use
currentColoror CSS custom properties
8. STROKE WEIGHT CONSISTENCY (Low)
Lucide icons default to strokeWidth={2}. At xl / 2xl sizes used in marketing sections, strokeWidth={1.5} looks more refined. Never mix 1.5 and 2 in the same UI region.
Search for strokeWidth= props on icons and verify they follow the pattern:
xs–lgsizes:strokeWidth={2}(default, can omit)xl–2xlsizes:strokeWidth={1.5}preferred
Fixing Protocol
- Read each file first before editing.
- Fix critical issues first (mixed libraries, a11y), then high, then medium, then low.
- Never modify
src/components/ui/*(shadcn internals). - Batch edits per file — fix all issues in a file in one edit.
- If
<Icon>wrapper doesn't exist, note it for icon-system to create — don't create it inline here.
Output Format
## Icon & Illustration Audit Report
### Summary
- Files scanned: X
- Violations found: X (Critical: X, High: X, Medium: X, Low: X)
- Auto-fixed: X
- Manual review needed: X
### Critical: Icon Wrapper Missing
[ ] src/components/ui/icon.tsx does not exist → Run /icon-system to create it
### Violations by Category
#### 1. MIXED LIBRARIES — X violations
| File | Line | Violation | Fix |
|------|------|-----------|-----|
#### 2. RAW LUCIDE USAGE — X violations
| File | Line | Violation | Fix |
|------|------|-----------|-----|
#### 3. ARBITRARY SIZES — X violations
...
#### 4. HARDCODED COLORS — X violations
...
#### 5. FLEX COMPRESSION — X violations
...
#### 6. ACCESSIBILITY — X violations
...
#### 7. ILLUSTRATIONS — X violations
...
#### 8. STROKE WEIGHT — X violations
...
### Files Modified
- path/to/file.tsx — X fixes applied
### Remaining Manual Work
- Items that require design decisions or new assets