Skip to main content
ClaudeWave
Skill1.2k estrellas del repoactualizado 3d ago

design-audit

Design audit checklist - motion gaps, accessibility, color consistency, responsive, performance.

Instalar en Claude Code
Copiar
git clone --depth 1 https://github.com/Jwuthri/Tracely-ai /tmp/design-audit && cp -r /tmp/design-audit/.agents/skills/design-audit ~/.claude/skills/design-audit
Después abre una sesión nueva de Claude Code; el skill carga automáticamente.

SKILL.md

# Design Audit

> The final checkpoint. Loaded by `/genjutsu:paint` at the end of the pipeline.
> Scans the codebase for motion gaps, a11y violations, perf issues, and inconsistencies.

---

## Motion Gap Analysis

Run these greps against the project to detect missing animations.

### Conditional renders without AnimatePresence

```bash
grep -rn '{.*&&\s*<\|{.*?\s*:\s*<\|{.*ternary.*<' --include='*.tsx' --include='*.jsx' src/ | grep -v 'AnimatePresence'
```

Look for: `{show && <Component />}` or ternary renders without a wrapping `<AnimatePresence>`. Every conditional mount/unmount needs exit animation support.

### Hover states without transition

```bash
grep -rn ':hover' --include='*.css' --include='*.scss' --include='*.module.css' src/ | grep -vE 'transition|animation'
```

Every `:hover` rule must have a corresponding `transition` on the base selector. Instant state flips feel broken.

### Dynamic lists without stagger

```bash
grep -rn '\.map(' --include='*.tsx' --include='*.jsx' src/ | grep -vE 'stagger|delay.*index|variants|transition.*delay'
```

Lists rendered via `.map()` should stagger their entrance. Simultaneous pop-in looks cheap.

### Style changes without transition

```bash
grep -rn 'style={{' --include='*.tsx' --include='*.jsx' src/ | grep -vE 'transition|transform|opacity'
```

Inline style changes (e.g., dynamic background, color) need a CSS transition or motion wrapper.

### Entries without corresponding exits

```bash
grep -rn 'initial=' --include='*.tsx' --include='*.jsx' src/ | grep -v 'exit='
```

Every Framer Motion `initial` + `animate` should have an `exit` prop when inside `AnimatePresence`.

---

## Accessibility Audit

### Reduced motion - MANDATORY

A project with animation MUST have at least one global handler matching its stack. Run all 3 greps:

```bash
# Web
grep -rn 'prefers-reduced-motion' --include='*.css' --include='*.scss' --include='*.ts' --include='*.tsx' --include='*.js' --include='*.jsx' src/ 2>/dev/null

# SwiftUI / UIKit
grep -rn 'accessibilityReduceMotion\|isReduceMotionEnabled\|reduceMotionStatusDidChangeNotification' --include='*.swift' . 2>/dev/null

# Compose
grep -rn 'LocalAccessibilityManager\|isReduceTransitions\|TRANSITION_ANIMATION_SCALE\|ANIMATOR_DURATION_SCALE\|areTransitionsEnabled' --include='*.kt' . 2>/dev/null
```

**Zero results across all 3 in an animated project = critical violation.** At least one handler must exist somewhere. Cross-reference `motion-principles/SKILL.md` for canonical implementations per stack.

### Contrast ratio 4.5:1

- Use browser DevTools (Inspect > color swatch > contrast ratio)
- Run `npx pa11y <url>` or Lighthouse accessibility audit
- Check animated text at mid-transition -- fading text must remain readable at every opacity above 0.4

### Focus visible on all interactives

```bash
grep -rn 'outline:\s*none\|outline:\s*0' --include='*.css' --include='*.scss' --include='*.module.css' src/
```

Any `outline: none` MUST be paired with a custom `:focus-visible` style. Removing focus rings without replacement is a WCAG failure.

### Semantic HTML -- no clickable divs

```bash
grep -rn 'onClick' --include='*.tsx' --include='*.jsx' src/ | grep -E '<div|<span' | grep -v 'role='
```

Every `<div onClick>` or `<span onClick>` must either be a `<button>`, an `<a>`, or have `role="button"` + `tabIndex` + `onKeyDown`.

### ARIA on decorative animations

```bash
grep -rn '<motion\.\|<animated\.\|<Lottie\|<Canvas' --include='*.tsx' --include='*.jsx' src/ | grep -v 'aria-hidden'
```

Purely decorative animations (background particles, ambient motion, Lottie illustrations) must have `aria-hidden="true"` to avoid polluting screen readers.

---

## Performance Audit

### Layout thrashing -- animating layout properties

```bash
grep -rn 'transition.*\(width\|height\|top\|left\|right\|bottom\|margin\|padding\)' --include='*.css' --include='*.scss' --include='*.module.css' src/
```

Animating layout properties triggers reflow every frame. Replace with `transform: translate/scale` and `opacity`.

### Excessive paint triggers

```bash
grep -rn 'will-change' --include='*.css' --include='*.scss' --include='*.module.css' src/
```

`will-change` should be rare and scoped. If more than ~5 elements use it permanently, the GPU memory cost outweighs the benefit. Apply it dynamically (add on hover/focus, remove on animation end).

### Animation library bundle cost

Check actual impact:

```bash
npx source-map-explorer dist/**/*.js 2>/dev/null || npx vite-bundle-visualizer 2>/dev/null
```

Reference sizes (gzipped): framer-motion ~30KB, GSAP ~25KB, popmotion ~5KB, CSS-only = 0KB. If the project only uses fade+slide, a 30KB lib is overkill.

On mobile native, the APK / IPA size matters. A third-party animation library adds typically 500KB-2MB:

| Library | Size impact (uncompressed) |
|---|---|
| Lottie (iOS) | ~600KB |
| Lottie (Android) | ~900KB |
| Rive (iOS) | ~1.5MB |
| Rive (Android) | ~2MB |
| Native Compose / SwiftUI animations | 0KB (built-in) |

If the project only uses fades, slides, and springs, native APIs (Compose `animate*AsState` + spring, SwiftUI `withAnimation`) are sufficient. Justify a Lottie / Rive dependency only for genuinely complex pre-designed animations (e.g., onboarding illustrations).

### requestAnimationFrame vs setTimeout

```bash
grep -rn 'setTimeout\|setInterval' --include='*.ts' --include='*.tsx' --include='*.js' --include='*.jsx' src/ | grep -iE 'anim\|motion\|scroll\|position\|style\|transform'
```

Animation loops must use `requestAnimationFrame`. `setTimeout`/`setInterval` causes frame drops and doesn't pause in background tabs.

---

## Consistency Audit

### Duration consistency

```bash
grep -rnoE 'duration[:"'\''= ]+[0-9.]+' --include='*.tsx' --include='*.jsx' --include='*.ts' --include='*.css' --include='*.scss' src/ | sort -t: -k3 | uniq -c -f2 | sort -rn
```

A well-designed project uses 3-5 distinct durations max (e.g., 0.15, 0.25, 0.35, 0.5). If you see 15 different values, extract