
Design Review
- 184 installs
- 202 repo stars
- Updated August 4, 2026
- secondsky/claude-skills
Use design-review for development tasks
About
design-review: A skill for development. This provides functionality for development workflows.
- design-review
Design Review by the numbers
- 184 all-time installs (skills.sh)
- +15 installs in the week ending Aug 5, 2026 (Skillselion tracking)
- Ranked #2,176 of 4,347 Backend & APIs skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/secondsky/claude-skills --skill design-reviewAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 184 |
|---|---|
| repo stars | ★ 202 |
| Last updated | August 4, 2026 |
| Repository | secondsky/claude-skills ↗ |
What it does
Use design-review for development tasks
Files
Design Review Skill
Status: Production Ready ✅ Last Updated: 2025-11-20 Dependencies: Playwright MCP or Chrome DevTools Methodology: 7-phase systematic review (inspired by Stripe, Airbnb, Linear)
---
Quick Start
1. Prerequisites Check
Before starting a design review, verify browser automation tools are available:
Option A: Playwright MCP (recommended for interactive testing)
- See the
playwright-testingskill for Playwright setup - Provides browser automation, screenshots, viewport testing, console monitoring
Option B: Chrome DevTools CLI (alternative for screenshots and performance)
- See the
chrome-devtoolsskill for Puppeteer CLI setup - Provides screenshot capture, performance analysis, network monitoring
For complete browser tools reference, see references/browser-tools-reference.md.
2. Understand the Review Scope
For PR reviews:
# Analyze git diff to understand scope
git diff --name-only origin/main...HEAD
# Read PR description for contextFor general UI reviews: Simply provide the preview URL and component/page description.
3. Execute 7-Phase Review
Follow the systematic checklist below. Each phase has specific objectives and testing procedures.
---
The 7-Phase Review Methodology
Phase 0: Preparation
Objective: Understand context and set up testing environment.
Steps: 1. Read PR description or review request to understand:
- Motivation for changes
- Scope of implementation
- Testing notes from developer
- Expected behavior
2. Analyze code diff (if PR available):
git diff origin/main...HEADIdentify modified files (components, styles, tests)
3. Set up live preview environment:
- Navigate to preview URL using browser tools
- Set initial viewport: 1440x900 (desktop)
- Take baseline screenshot for reference
4. Review design principles (if project has custom guidelines):
- Check project CLAUDE.md for design standards
- Review component library documentation
- Note design system tokens and patterns
When to skip: For quick component reviews without git context.
---
Phase 1: Interaction & User Flow
Objective: Verify the interactive experience works as expected.
For complete interaction guide: Load references/interaction-patterns.md when testing interactive states, forms, buttons, navigation flows, micro-interactions, modals, or keyboard navigation.
Quick checklist:
- Test 5 interactive states (default, hover, active, focus, disabled) for all elements
- Execute primary user flow (form submission, navigation, key actions)
- Verify destructive actions have confirmation dialogs
- Assess perceived performance (loading states, optimistic UI)
Triage: [Blocker] Critical flow broken | [High] Poor UX/missing focus states | [Medium] Missing polish | [Nitpick] Minor timing issues
---
Phase 2: Responsiveness Testing
Objective: Ensure design works across all viewport sizes.
For complete responsive guide: Load references/responsive-testing.md when testing viewports, touch targets, mobile navigation, image responsiveness, or debugging horizontal scrolling.
Test 3 viewports:
- Desktop (1440px): Optimal layout, full feature set
- Tablet (768px): Graceful adaptation, 44×44px touch targets, collapsing nav
- Mobile (375px): No horizontal scroll, 16px min text, mobile-friendly navigation
Quick testing:
mcp__playwright__browser_resize(width: 1440, height: 900) # Desktop
mcp__playwright__browser_resize(width: 768, height: 1024) # Tablet
mcp__playwright__browser_resize(width: 375, height: 667) # Mobile
mcp__playwright__browser_take_screenshot(fullPage: true)Triage: [Blocker] Layout broken | [High] Horizontal scroll/overlapping | [Medium] Suboptimal spacing | [Nitpick] Minor inconsistencies
---
Phase 3: Visual Polish
Objective: Assess aesthetic quality and visual consistency.
For design principles guide: Load references/visual-polish.md when evaluating typography hierarchy, spacing/layout, color palette, alignment/grid, visual hierarchy, image quality, or S-Tier design standards.
Quick evaluation (5 criteria): 1. Layout & spacing: Grid alignment, 8px scale, design tokens (no magic numbers like 17px) 2. Typography: Clear H1>H2>H3 hierarchy, 1.5-1.7 line height, limited font weights 3. Color: Design system tokens, semantic usage (red=error, green=success), consistent brand 4. Images: High-res (no pixelation), correct aspect ratios, optimized sizes, alt text 5. Visual hierarchy: Primary actions stand out, eye flows naturally, strategic whitespace
Triage: [Blocker] Illegible text/broken images | [High] Obvious inconsistencies | [Medium] Spacing/alignment issues | [Nitpick] Aesthetic preferences
---
Phase 4: Accessibility (WCAG 2.1 AA)
Objective: Ensure inclusive design for all users.
For complete WCAG 2.1 AA checklist: Load references/accessibility-wcag.md when verifying WCAG compliance, testing keyboard navigation, checking color contrast, auditing semantic HTML, or using accessibility testing tools (Lighthouse, axe, WAVE).
Quick WCAG tests (4 principles):
1. Perceivable: Alt text on images, color contrast (4.5:1 text, 3:1 UI components), semantic HTML 2. Operable: Keyboard navigation (Tab order logical, visible focus on ALL interactive elements, Enter/Space activation, Escape closes modals, no keyboard traps) 3. Understandable: Clear labels, helpful error messages, consistent navigation/terminology 4. Robust: Valid HTML, proper ARIA attributes (roles, states, properties)
Critical tests:
- Tab through entire page (verify focus states visible, logical order, no traps)
- Test with WebAIM Contrast Checker (all text/UI ≥4.5:1 or 3:1)
- Verify form labels associated with inputs (
<label for="id">oraria-label) - Check semantic HTML (h1→h2→h3 no skipping,
<button>not<div onClick>)
Triage: [Blocker] No keyboard access to core features | [High] WCAG AA violations | [Medium] Semantic HTML issues | [Nitpick] Enhanced accessibility
---
Phase 5: Robustness Testing
Objective: Verify handling of edge cases and error conditions.
Test scenarios:
5.1 Form Validation
- Submit form with empty required fields
- Enter invalid data (wrong email format, out-of-range numbers)
- Test field-level validation (real-time feedback)
- Verify clear error messages with guidance
- Test successful submission flow (confirmation message)
5.2 Content Overflow
- Long text strings: Very long names, emails, titles
- Many items: Large lists, tables with hundreds of rows
- Deeply nested content: Comments with many replies
- Empty states: No data to display (show helpful message)
Common overflow issues:
- Text breaking layout (overflowing containers)
- Truncation without ellipsis or tooltip
- Performance issues with large lists
- Missing empty state designs
5.3 Loading & Error States
- Loading states: Skeleton screens, spinners, progress indicators
- Error messages: Clear, actionable error descriptions
- Retry mechanisms: Allow user to retry failed operations
- Timeout handling: Graceful handling of slow/failed requests
- Optimistic updates: Immediate feedback, rollback on failure
Test procedure:
# Simulate slow network
# Check browser DevTools Network tab → throttling
# Force error states
# Test with invalid API responses or network failuresCommon problems:
- No loading indicators (appears frozen)
- Vague error messages ("Error occurred")
- No retry mechanism after failures
- Layout jumps when content loads
Triage priorities:
- [Blocker] Crashes or complete failures under edge cases
- [High] Poor error handling or confusing states
- [Medium] Missing edge case handling or minor issues
- [Nitpick] Loading state aesthetics or minor polish
---
Phase 6: Code Health
Objective: Ensure maintainable, consistent implementation.
For code patterns guide: Load references/code-health-patterns.md when evaluating component reuse (DRY principle), design token usage (colors, spacing, typography), pattern consistency (naming, file structure, API patterns), or identifying red flags (duplication, magic numbers, broken abstractions).
Quick review (3 criteria): 1. Component reuse: No copy-paste, shared components extracted, composition over duplication 2. Design tokens: CSS variables for colors/spacing/typography (no magic numbers like margin: 17px), border radii consistent 3. Pattern consistency: Follows codebase patterns, naming conventions match, file structure organized
Triage: [High] Introduces tech debt/breaks patterns | [Medium] Missed reuse opportunities | [Nitpick] Code style preferences
---
Phase 7: Content & Console
Objective: Verify polished details and technical correctness.
7.1 Content Review
Check for:
- Grammar and spelling: No typos or grammatical errors
- Clarity: Labels and instructions are unambiguous
- Tone consistency: Matches brand voice (formal/casual)
- Placeholder text: Replaced with real content (no "Lorem ipsum")
- Microcopy quality: Helpful error messages, button labels, tooltips
Common content issues:
- Typos in UI text
- Placeholder text left in production
- Vague labels ("Submit" vs "Save Changes")
- Inconsistent terminology
- Unhelpful error messages ("Error" vs "Email format invalid")
7.2 Console Check
Test procedure:
# Using Playwright MCP
mcp__playwright__browser_console_messages()
# Using Chrome DevTools
# Open DevTools → Console tabLook for:
- JavaScript errors: Uncaught exceptions, null references
- React warnings: Key prop warnings, lifecycle issues
- Network failures: Failed API requests, 404s
- Deprecation warnings: Old API usage warnings
- Performance warnings: Slow renders, memory leaks
Triage priorities:
- [Blocker] Console errors breaking functionality
- [High] Grammar errors or confusing content in user-facing text
- [Medium] Console warnings or minor content issues
- [Nitpick] Content polish, minor console noise
---
Communication Principles
1. Problems Over Prescriptions
Describe the problem and its impact, not the solution. Let the developer decide implementation.
❌ Prescriptive (avoid): "Change the margin to 16px"
✅ Problem-focused (preferred): "The spacing feels inconsistent with adjacent elements, creating visual clutter that distracts from the primary CTA. The current spacing breaks the established rhythm of the design system."
2. Triage Matrix
Categorize every issue with clear priority:
| Priority | Criteria | Action Required |
|---|---|---|
| [Blocker] | Critical failures, core functionality broken, critical accessibility violations | Must fix before merge |
| [High-Priority] | Significant UX issues, obvious design inconsistencies, WCAG violations | Should fix before merge |
| [Medium-Priority] | Improvements, minor inconsistencies, edge case handling | Consider for follow-up PR |
| [Nitpick] | Aesthetic preferences, minor polish, subjective opinions | Optional refinements |
Important: Prefix all nitpicks with "Nit:" to signal low priority.
3. Evidence-Based Feedback
Always provide screenshots for visual issues. Screenshots should:
- Show the problem clearly
- Include relevant context (surrounding elements)
- Indicate what to look at (arrows, highlights if needed)
Example:
### [High-Priority] Poor contrast on disabled button
**Problem:** Disabled button text has insufficient contrast (2.1:1), failing WCAG AA
standard (requires 4.5:1). Users with low vision may not recognize the button as disabled.
**Screenshot:** [Attach screenshot showing disabled button]
**Impact:** Accessibility violation, potential confusion for users with visual impairments.4. Start with Positives
Always acknowledge what works well before listing issues. This:
- Shows you recognize good work
- Provides balanced feedback
- Maintains positive collaboration
Example:
### Design Review Summary
The new checkout flow shows excellent attention to user experience. The step indicator
is clear and well-designed, error messages are helpful and actionable, and the overall
layout feels spacious and uncluttered. The loading states with skeleton screens are
particularly well-executed. Great work on the form validation feedback!
However, there are a few accessibility and responsiveness issues to address before merge...---
Report Structure Template
For complete template: Load assets/review-report-template.md for the full markdown template with all sections and examples.
Essential structure:
## Design Review Summary
[2-3 sentences: positive acknowledgment + overall assessment]
**Review scope:** [PR #, pages, components]
**Viewports tested:** Desktop (1440px), Tablet (768px), Mobile (375px)
**Methodology:** 7-phase comprehensive review
---
### Findings
#### 🚨 Blockers
[Critical issues requiring immediate fix before merge]
- **[Blocker] [Title]**: Problem + Screenshot + Phase
#### ⚠️ High-Priority Issues
[Significant issues to fix before merge]
- **[High] [Title]**: Problem + Screenshot + Phase
#### 📋 Medium-Priority / Suggestions
[Improvements for follow-up PR]
- **[Medium] [Title]**: Problem + Phase
#### ✨ Nitpicks
[Minor aesthetic details - optional]
- **Nit:** [Issue] - [Brief description]
---
### Testing Evidence
**Screenshots:** Desktop (1440px) + Tablet (768px) + Mobile (375px)
**Console output:** [Errors/warnings or "Console clean"]
**Accessibility:** Keyboard nav + Focus states + Color contrast
---
### Next Steps
1. Fix Blockers
2. Address High-Priority issues
3. Consider Medium-Priority items
**Overall assessment:** [Ready to merge after blockers fixed / Needs revisions / Ready to merge!]---
When to Load References
Load reference files when working on specific aspects of design review:
accessibility-wcag.md
Load when:
- Standards-based: Verifying WCAG 2.1 AA compliance for production deployment
- Issue-based: Encountering accessibility violations (color contrast, keyboard navigation, semantic HTML, focus states, ARIA attributes)
- Testing-based: Conducting comprehensive accessibility audit with systematic checklist
- Tools-based: Using accessibility testing tools (Lighthouse, axe, WAVE, Pa11y) for automated testing
- Triage-based: Determining severity of accessibility issues (Blocker/High/Medium for WCAG violations)
browser-tools-reference.md
Load when:
- Setup-based: Installing or configuring Playwright MCP or Chrome DevTools CLI for testing
- Command-based: Need specific Playwright commands (navigate, resize viewport, screenshot, click, type, hover, get console output)
- Workflow-based: Implementing common testing workflows (responsive review across 3 viewports, form interaction testing, keyboard navigation testing)
- Selector-based: Struggling with CSS selectors, text selectors, or accessibility selectors for element targeting
- Troubleshooting-based: Playwright MCP not finding elements, Chrome dependencies missing, screenshot capture issues
code-health-patterns.md
Load when:
- Pattern-based: Evaluating component reuse patterns, DRY principle compliance, extracting shared components
- Token-based: Checking design token usage (colors, spacing scale, typography scale, border radii consistency)
- Consistency-based: Reviewing pattern consistency (naming conventions, file structure organization, API patterns, state management)
- Example-based: Need code examples comparing good vs bad patterns (inline styles vs tokens, duplication vs composition)
- Red-flag-based: Identifying code health issues (copy-paste duplication, magic numbers like
17px, inconsistent state management, broken abstractions)
design-principles-s-tier.md
Load when:
- Standards-based: Ensuring S-Tier SaaS dashboard quality (Stripe, Airbnb, Linear, Vercel level polish)
- System-based: Evaluating design system foundation (color palette structure, typography scale, spacing scale, core UI components)
- Module-based: Reviewing specific modules (multimedia moderation interfaces, data tables, configuration panels, dashboards)
- Philosophy-based: Applying core design philosophy (users first, meticulous craft over speed, simplicity over complexity, consistency)
- Architecture-based: Evaluating CSS & styling architecture (design tokens, component patterns, responsive strategies)
interaction-patterns.md
Load when:
- States-based: Testing interactive states (default, hover, active, focus, disabled) for buttons, inputs, links
- Form-based: Testing form interactions, validation patterns, error states, success states, loading states
- Button-based: Evaluating button loading states, destructive action confirmation patterns, primary vs secondary actions
- Flow-based: Testing navigation flows, user journeys, multi-step processes, modal interactions
- Animation-based: Reviewing micro-interactions, animation timing (200-300ms), perceived performance (optimistic UI, skeleton screens)
- Modal-based: Testing modal interactions, keyboard traps, focus management, Escape key behavior
responsive-testing.md
Load when:
- Viewport-based: Testing at specific viewports (desktop 1440px, tablet 768px, mobile 375px) with Playwright MCP
- Touch-based: Verifying touch target sizes meet minimum 44×44px requirement for mobile usability
- Overflow-based: Debugging horizontal scrolling issues or layout overflow problems on mobile
- Mobile-based: Ensuring text readability (16px minimum font size), mobile navigation patterns, responsive images
- Breakpoint-based: Implementing or testing breakpoint strategy (common breakpoints: 640px, 768px, 1024px, 1280px)
- Navigation-based: Testing responsive navigation patterns (hamburger menus, collapsing navigation, mobile drawer menus)
visual-polish.md
Load when:
- Typography-based: Evaluating font hierarchy (H1>H2>H3), font scale standards (16/18/24/32/48/64px), line height (1.5-1.7), readability
- Spacing-based: Checking 8-point grid compliance (8/16/24/32/40/48/64px), consistent spacing scale, component padding/margin
- Color-based: Verifying color palette consistency, semantic color usage (red=error, green=success), design token usage (no hardcoded hex values)
- Alignment-based: Checking grid-based layout, precise alignment (0.5px precision), vertical rhythm, visual balance
- Hierarchy-based: Evaluating visual hierarchy techniques (size contrast, weight contrast, color contrast, position, strategic whitespace)
- Quality-based: Assessing image quality (no pixelation), correct aspect ratios, proper image optimization for web
- Component-based: Reviewing design system components (button styles, form input styles, card components, consistent border radii)
---
Known Issues Prevention
This skill prevents 8 documented design review issues:
| Issue | Problem | Impact | Prevention |
|---|---|---|---|
| #1: Missing Accessibility | Reviews focus only on visual appearance, ignoring keyboard navigation and screen readers | WCAG violations shipped to production, excluding users with disabilities | Phase 4 enforces complete WCAG 2.1 AA checklist with keyboard testing |
| #2: Incomplete Responsive Testing | Reviewing only at desktop viewport, missing mobile breakage | Broken mobile layouts, frustrated mobile users | Phase 2 requires testing at 1440px, 768px, and 375px viewports |
| #3: Vague Feedback | Comments like "looks off" without screenshots or specifics | Wasted time, unclear action items, frustrated developers | Evidence-based feedback principle requires screenshots |
| #4: Prescriptive Solutions | Dictating implementation ("change margin to 16px") instead of describing UX impact | Design-dev friction, missed better solutions | "Problems Over Prescriptions" principle enforced |
| #5: No Triage Priority | All feedback treated equally, blocking merges on nitpicks | Slowed delivery, unclear priorities | Triage matrix (Blocker/High/Medium/Nitpick) required |
| #6: Skipped Edge Cases | Happy path works, but error states and overflow break layout | Production bugs with edge cases | Phase 5 mandates robustness testing |
| #7: Console Errors Ignored | Visual design passes, but JavaScript errors exist in console | Runtime failures, poor user experience | Phase 7 requires console check |
| #8: Inconsistent Methodology | Ad-hoc reviews miss critical areas depending on reviewer mood | Incomplete reviews, missed issues | 7-phase checklist ensures comprehensive, repeatable reviews |
---
Dependencies
Required
Browser automation tools (one of the following):
1. Playwright MCP (recommended)
- See
playwright-testingskill for installation - Provides: Browser automation, screenshots, viewport testing, console monitoring
- Best for: Interactive testing, keyboard navigation, form testing
2. Chrome DevTools CLI
- See
chrome-devtoolsskill for installation - Provides: Screenshot capture, performance analysis, network monitoring
- Best for: Visual testing, performance audits
Live preview environment:
- URL accessible for testing
- Represents actual implementation (not mockups)
Optional
- Git/GitHub: For PR context and diff analysis
- Design system docs: For consistency checks against established patterns
- Project CLAUDE.md: For project-specific design guidelines
Installation Guidance
If browser tools are not available, this skill will: 1. Detect missing tools 2. Link to appropriate skill for installation (playwright-testing or chrome-devtools) 3. Provide fallback guidance for manual testing
---
Related Skills
- playwright-testing: E2E testing with Playwright, browser automation setup
- chrome-devtools: Browser automation via Puppeteer CLI scripts
- frontend-design: Create new frontend interfaces with design quality (complementary skill)
- tailwind-v4-shadcn: UI framework implementation (designs being reviewed may use this)
- ai-sdk-ui: AI-powered UI components (may be part of reviewed interfaces)
---
Official Documentation
- WCAG 2.1 Guidelines: https://www.w3.org/WAI/WCAG21/quickref/
- WebAIM Contrast Checker: https://webaim.org/resources/contrastchecker/
- Playwright Documentation: https://playwright.dev/
- Inclusive Design Principles: https://inclusivedesignprinciples.org/
- A11y Project Checklist: https://www.a11yproject.com/checklist/
---
Production Validation
This skill is based on real design review workflows used at:
- Methodology inspiration: Stripe, Airbnb, Linear (7-phase systematic approach)
- Testing approach: Automated browser testing with Playwright/Puppeteer
- Accessibility standards: WCAG 2.1 AA compliance (industry standard)
Estimated token efficiency:
- Without skill: ~25k tokens (trial-and-error, repeated corrections)
- With skill: ~8k tokens (guided methodology, systematic approach)
- Savings: ~68% with 100% checklist coverage
---
Questions or issues?
1. Check references/accessibility-wcag.md for complete WCAG checklist 2. See references/browser-tools-reference.md for Playwright/Chrome DevTools commands 3. Review references/visual-polish.md for design principles 4. Verify browser tools are installed (see playwright-testing or chrome-devtools skills) 5. Ensure preview URL is live and accessible
Design Review Checklist Template
Copy this checklist at the start of each design review to track progress through all 7 phases.
---
Review Information
PR/Feature: [PR #XXX or Feature name] Preview URL: [https://preview.example.com] Reviewer: [Your name] Date: [YYYY-MM-DD]
---
Design Review Progress
- [ ] Phase 0: Preparation
- [ ] Phase 1: Interaction & User Flow
- [ ] Phase 2: Responsiveness
- [ ] Phase 3: Visual Polish
- [ ] Phase 4: Accessibility
- [ ] Phase 5: Robustness
- [ ] Phase 6: Code Health
- [ ] Phase 7: Content & Console---
Phase 0: Preparation
- [ ] Read PR description / review request
- [ ] Analyzed code diff (
git diff origin/main...HEAD) - [ ] Set up live preview environment
- [ ] Navigated to preview URL using browser tools
- [ ] Set viewport to 1440×900 (desktop)
- [ ] Captured baseline screenshot
Notes: [Any context or observations from preparation]
---
Phase 1: Interaction & User Flow
Primary User Flow
- [ ] Executed primary user flow (based on PR notes)
- [ ] Verified success states and confirmation messages
Primary flow: [Describe the flow tested]
Interactive States
- [ ] Hover states - Verified visual feedback on mouse over
- [ ] Active/Pressed states - Verified down state when clicking
- [ ] Focus states - Verified clear outline for keyboard navigation
- [ ] Disabled states - Verified visually distinct, non-interactive
Elements tested: [List key interactive elements]
Other Checks
- [ ] Destructive actions have confirmations
- [ ] Perceived performance feels snappy (<100ms feedback)
- [ ] Loading states shown for async operations
Issues found: [Number] - [Brief list]
Status: ✅ Pass / ⚠️ Issues found
---
Phase 2: Responsiveness
Desktop (1440px)
- [ ] Resized to 1440×900
- [ ] Captured full-page screenshot
- [ ] Verified optimal layout
- [ ] Checked all content accessible without excessive scrolling
Screenshot: [Reference or attach]
Tablet (768px)
- [ ] Resized to 768×1024
- [ ] Captured full-page screenshot
- [ ] Verified layout adapts gracefully
- [ ] Checked touch target sizes (minimum 44px)
- [ ] Verified navigation collapses appropriately
Screenshot: [Reference or attach]
Mobile (375px)
- [ ] Resized to 375×667
- [ ] Captured full-page screenshot
- [ ] No horizontal scrolling ✓
- [ ] Text readable (16px minimum for body)
- [ ] Touch targets adequate (44px minimum)
- [ ] Mobile navigation works (hamburger menu, etc.)
Screenshot: [Reference or attach]
Issues found: [Number] - [Brief list]
Status: ✅ Pass / ⚠️ Issues found
---
Phase 3: Visual Polish
Typography
- [ ] Clear heading hierarchy (H1 > H2 > H3)
- [ ] Appropriate font sizes and weights
- [ ] Adequate line height (1.5+ for body text)
- [ ] Consistent font families (1-2 max)
Spacing & Layout
- [ ] Consistent spacing scale (8px multiples)
- [ ] No magic numbers (random pixel values)
- [ ] Design token usage (var(--space-X))
- [ ] Elements aligned precisely (no 1px offsets)
- [ ] Adequate white space
Color
- [ ] Limited palette (consistent with design system)
- [ ] Semantic color usage (red=error, green=success)
- [ ] Design tokens used (var(--color-X))
- [ ] No hardcoded color values
Visual Hierarchy
- [ ] Primary actions stand out
- [ ] Eye naturally flows to important elements
- [ ] Related items grouped through proximity
- [ ] Contrast creates focus
Images
- [ ] High quality (no pixelation)
- [ ] Correct aspect ratios
- [ ] Responsive scaling
- [ ] Alt text present
Issues found: [Number] - [Brief list]
Status: ✅ Pass / ⚠️ Issues found
---
Phase 4: Accessibility (WCAG 2.1 AA)
Keyboard Navigation
- [ ] Tabbed through all interactive elements
- [ ] Verified logical tab order (left-to-right, top-to-bottom)
- [ ] Visible focus states on ALL elements ✓
- [ ] Enter/Space activates buttons and links
- [ ] Escape closes modals
- [ ] No keyboard traps
Elements tested: [List key elements]
Semantic HTML
- [ ] Proper heading hierarchy (h1 → h2 → h3, no skipping)
- [ ] Landmark regions present (
<nav>,<main>,<aside>,<footer>) - [ ] Form labels associated with inputs
- [ ] Buttons are
<button>, links are<a> - [ ] Lists use proper structure (
<ul>/<ol>+<li>)
Color Contrast
- [ ] Body text: 4.5:1 minimum ✓
- [ ] Large text: 3:1 minimum ✓
- [ ] UI components: 3:1 minimum ✓
- [ ] Disabled state text visible (3:1 minimum)
Contrast violations: [List any with ratios]
Form Accessibility
- [ ] Every input has associated
<label> - [ ] Error messages associated (aria-describedby)
- [ ] Required fields marked (aria-required="true")
- [ ] Fieldsets group related inputs with
<legend>
Image Alt Text
- [ ] All meaningful images have descriptive alt text
- [ ] Decorative images use empty alt (
alt="") - [ ] Icon buttons have
aria-labelor visible text
Issues found: [Number] - [Brief list]
Status: ✅ Pass / ⚠️ Issues found
---
Phase 5: Robustness
Form Validation
- [ ] Submitted form with empty required fields
- [ ] Entered invalid data (wrong email format, etc.)
- [ ] Tested field-level validation (real-time feedback)
- [ ] Verified clear error messages with guidance
- [ ] Tested successful submission flow
Content Overflow
- [ ] Tested with long text strings (names, emails, titles)
- [ ] Tested with many items (large lists, tables)
- [ ] Tested deeply nested content
- [ ] Verified empty states (no data to display)
Overflow issues: [List any]
Loading & Error States
- [ ] Verified loading indicators (skeleton screens, spinners)
- [ ] Tested error messages (clear, actionable)
- [ ] Checked retry mechanisms
- [ ] Verified timeout handling
Issues found: [Number] - [Brief list]
Status: ✅ Pass / ⚠️ Issues found
---
Phase 6: Code Health
Component Reuse
- [ ] No copy-pasted components (DRY principle)
- [ ] Shared components extracted to common location
- [ ] Component composition used appropriately
Design Token Usage
- [ ] Colors use CSS variables or design tokens
- [ ] Spacing uses design system scale
- [ ] Typography follows type scale
- [ ] Border radii consistent with design system
Hardcoded values found: [List any]
Pattern Consistency
- [ ] Follows established code patterns
- [ ] Naming conventions match existing code
- [ ] File structure consistent with project
- [ ] Similar problems solved similarly
Issues found: [Number] - [Brief list]
Status: ✅ Pass / ⚠️ Issues found
---
Phase 7: Content & Console
Content Review
- [ ] Grammar and spelling correct
- [ ] Labels and instructions clear and unambiguous
- [ ] Tone consistent with brand voice
- [ ] Placeholder text replaced with real content
- [ ] Microcopy helpful (error messages, button labels, tooltips)
Typos/grammar issues: [List any]
Console Check
- [ ] Ran console check using browser tools
- [ ] Console clean (no errors) ✓
Console output:
[Paste console output or note "Clean - no errors or warnings"]Errors found: [List JavaScript errors, React warnings, network failures, etc.]
Issues found: [Number] - [Brief list]
Status: ✅ Pass / ⚠️ Issues found
---
Summary
Issues by Priority
Blockers: [Number]
- [List blocker titles]
High-Priority: [Number]
- [List high-priority titles]
Medium-Priority: [Number]
- [List medium-priority titles]
Nitpicks: [Number]
- [List nitpick titles]
Total issues: [Number]
Phases Passed Completely
- [List phases with no issues - e.g., "Phase 1: Interaction", "Phase 7: Content & Console"]
Phases with Issues
- [List phases with findings - e.g., "Phase 2: Responsiveness (3 issues)", "Phase 4: Accessibility (2 issues)"]
---
Overall Assessment
[Choose one:]
- [ ] ✅ Ready to merge - No blocking issues found
- [ ] ⚠️ Ready to merge after blockers fixed - [X] blocker(s) must be resolved
- [ ] 🛑 Needs revisions - Multiple high-priority issues require attention
Reasoning: [1-2 sentences]
---
Next Steps
Before merge: 1. [Action 1] 2. [Action 2]
Follow-up (next sprint/PR): 1. [Action 1] 2. [Action 2]
Optional refinements:
- [Nitpick 1]
- [Nitpick 2]
---
Review Complete
Completed by: [Your name] Date: [YYYY-MM-DD] Time spent: [Approximate time]
Additional notes: [Any additional context or observations]
---
Quick Copy-Paste Checklist (Compact Version)
For quick tracking during review:
Design Review Progress Tracker:
[ ] Phase 0: Preparation (analyze changes, set up preview)
[ ] Phase 1: Interaction & User Flow (test primary flows)
[ ] Phase 2: Responsiveness (desktop/tablet/mobile)
[ ] Phase 3: Visual Polish (typography, spacing, colors)
[ ] Phase 4: Accessibility (WCAG 2.1 AA)
[ ] Phase 5: Robustness (edge cases, error states)
[ ] Phase 6: Code Health (component reuse, design tokens)
[ ] Phase 7: Content & Console (grammar, errors)
Issues Found:
- Blockers: 0
- High: 0
- Medium: 0
- Nitpicks: 0
Status: [ ] Ready / [ ] After fixes / [ ] Needs work---
Usage Tips:
1. Start each review by copying this checklist to track progress 2. Check off items as you complete them to ensure nothing is missed 3. Take notes in each section for reference when writing the full report 4. Use the compact version for quick tracking during live reviews 5. Save the completed checklist alongside the full design review report
Remember: This checklist ensures comprehensive, systematic reviews that catch issues across all 7 phases. Don't skip phases!
Design Review Report Template
Copy this template for all design reviews. Replace [bracketed content] with actual findings.
---
Design Review Summary
[2-3 sentences acknowledging what works well and providing overall assessment. Always start positive!]
Example:
The new checkout flow shows excellent attention to user experience. The step indicator is clear and well-designed, error messages are helpful and actionable, and the overall layout feels spacious and uncluttered. The loading states with skeleton screens are particularly well-executed. Great work on the form validation feedback!
Review scope: [What was reviewed - e.g., "PR #234: Redesigned user profile page" or "Complete checkout flow at /checkout"]
Viewports tested:
- Desktop: 1440px ✓
- Tablet: 768px ✓
- Mobile: 375px ✓
Methodology: 7-phase comprehensive review (Preparation, Interaction, Responsiveness, Visual Polish, Accessibility, Robustness, Content & Console)
Browser tools: [Playwright MCP / Chrome DevTools CLI]
Date: [YYYY-MM-DD]
---
Findings
🚨 Blockers
[Critical issues that MUST be fixed before merge. These prevent core functionality or create critical accessibility violations.]
If no blockers, state: "No blocking issues found."
---
[Blocker] [Issue Title]
Problem: [Describe the issue and its impact on users or functionality. Be specific about why this is critical.]
Example:
The submit button is completely inaccessible via keyboard. Users who rely on keyboard navigation cannot submit the form, making the entire feature unusable for keyboard-only users. This is a critical WCAG violation.
Screenshot: [Attach screenshot or note "No screenshot needed for functionality issue"]
Phase: [Which phase caught this - e.g., "Phase 4: Accessibility"]
How to verify: 1. [Step to reproduce] 2. [Expected behavior] 3. [Actual behavior]
---
[Blocker] [Another Issue Title]
[Repeat format for each blocker]
---
⚠️ High-Priority Issues
[Significant issues that SHOULD be fixed before merge. These cause noticeable UX problems or violate design standards.]
If no high-priority issues, state: "No high-priority issues found."
---
[High] [Issue Title]
Problem: [Describe the issue and why it's significant]
Example:
The primary button text has insufficient color contrast (2.8:1) against its background, failing WCAG AA requirements (4.5:1 minimum). Users with low vision or color blindness may have difficulty reading the button label.
Screenshot: [Attach screenshot showing the issue]
Phase: [Which phase caught this]
Suggested priority: Fix before merge
---
[High] [Another Issue Title]
[Repeat format for each high-priority issue]
---
📋 Medium-Priority / Suggestions
[Improvements that would enhance the experience but can be addressed in a follow-up PR.]
If no medium-priority issues, state: "No medium-priority suggestions."
---
[Medium] [Issue Title]
Problem: [Describe the improvement opportunity]
Example:
The card spacing is inconsistent - some cards use 16px padding while others use 20px. This breaks the visual rhythm. Standardizing to var(--space-4) (16px) would improve consistency.
Phase: [Which phase]
Suggested priority: Address in follow-up PR or next sprint
---
[Medium] [Another Issue Title]
[Repeat format for each medium-priority issue]
---
✨ Nitpicks
[Minor aesthetic details and optional refinements. Prefix all nitpicks with "Nit:" to clearly signal low priority.]
If no nitpicks, you can omit this section entirely.
- Nit: [Brief description] - [Why it might be better, but acknowledge it's subjective]
Examples:
- Nit: The success message could use a checkmark icon for quicker visual recognition - though the green color is already clear.
- Nit: Consider reducing the button border-radius from 8px to 6px for better alignment with the input fields - this is a minor aesthetic preference.
- Nit: The heading font-weight could be increased from 600 to 700 for slightly more emphasis - current weight is acceptable.
---
Testing Evidence
Screenshots Captured
Desktop (1440px): [Attach or reference desktop screenshot]
- URL: [Preview URL tested]
- Viewport: 1440 × 900
- Notes: [Any relevant observations]
Tablet (768px): [Attach or reference tablet screenshot]
- Viewport: 768 × 1024
- Notes: [Any relevant observations - e.g., "Navigation collapses to hamburger menu"]
Mobile (375px): [Attach or reference mobile screenshot]
- Viewport: 375 × 667
- Notes: [Any relevant observations - e.g., "No horizontal scrolling, forms stack vertically"]
Console Output
[Copy browser console output here]If console is clean:
Console clean - no JavaScript errors or warnings detected.
If errors present:
Console errors found:
- [Error 1: Description and file/line]
- [Error 2: Description and file/line]
Accessibility Testing Results
Keyboard Navigation:
- [✓ / ✗] All interactive elements keyboard accessible
- [✓ / ✗] Logical tab order (left-to-right, top-to-bottom)
- [✓ / ✗] Visible focus states on all elements
- [✓ / ✗] Enter/Space activates buttons and links
- [✓ / ✗] Escape closes modals
Notes: [Any specific findings - e.g., "Submit button missing focus state"]
Focus States:
- [✓ / ✗] All interactive elements have visible focus indicators
- [✓ / ✗] Focus indicators meet 3:1 contrast minimum
Notes: [Any specific findings]
Color Contrast:
- [✓ / ✗] Body text meets 4.5:1 minimum
- [✓ / ✗] Large text meets 3:1 minimum
- [✓ / ✗] UI components meet 3:1 minimum
Violations: [List any contrast failures with ratios]
Semantic HTML:
- [✓ / ✗] Proper heading hierarchy (h1 → h2 → h3)
- [✓ / ✗] Landmark regions present (nav, main, aside, footer)
- [✓ / ✗] Form labels associated with inputs
- [✓ / ✗] Buttons are <button>, links are <a>
Notes: [Any specific findings]
---
Phase-by-Phase Summary
Phase 0: Preparation
- [✓] PR description reviewed
- [✓] Code diff analyzed
- [✓] Preview environment set up
- [✓] Baseline screenshot captured
Phase 1: Interaction & User Flow
- [✓ / ✗] Primary user flow tested
- [✓ / ✗] Interactive states verified (hover, active, focus, disabled)
- [✓ / ✗] Destructive actions have confirmations
- Issues found: [Number] ([Blocker/High/Medium/Nitpick] count)
Phase 2: Responsiveness
- [✓ / ✗] Desktop (1440px) tested
- [✓ / ✗] Tablet (768px) tested
- [✓ / ✗] Mobile (375px) tested
- [✓ / ✗] No horizontal scrolling
- [✓ / ✗] Touch targets adequate (44px minimum)
- Issues found: [Number] ([Blocker/High/Medium/Nitpick] count)
Phase 3: Visual Polish
- [✓ / ✗] Typography hierarchy clear
- [✓ / ✗] Spacing consistent
- [✓ / ✗] Colors follow design system
- [✓ / ✗] Alignment precise
- [✓ / ✗] Visual hierarchy effective
- Issues found: [Number] ([Blocker/High/Medium/Nitpick] count)
Phase 4: Accessibility (WCAG 2.1 AA)
- [✓ / ✗] Keyboard navigation complete
- [✓ / ✗] Focus states visible
- [✓ / ✗] Color contrast meets AA
- [✓ / ✗] Semantic HTML correct
- [✓ / ✗] Form labels present
- [✓ / ✗] Image alt text provided
- Issues found: [Number] ([Blocker/High/Medium/Nitpick] count)
Phase 5: Robustness
- [✓ / ✗] Form validation tested
- [✓ / ✗] Content overflow handled
- [✓ / ✗] Loading states present
- [✓ / ✗] Error states clear
- Issues found: [Number] ([Blocker/High/Medium/Nitpick] count)
Phase 6: Code Health
- [✓ / ✗] Component reuse appropriate
- [✓ / ✗] Design tokens used
- [✓ / ✗] Follows established patterns
- Issues found: [Number] ([Blocker/High/Medium/Nitpick] count)
Phase 7: Content & Console
- [✓ / ✗] Grammar and spelling correct
- [✓ / ✗] Console clean (no errors)
- Issues found: [Number] ([Blocker/High/Medium/Nitpick] count)
---
Summary Statistics
Total issues found: [Number]
- Blockers: [Number]
- High-priority: [Number]
- Medium-priority: [Number]
- Nitpicks: [Number]
Phases with issues:
- [List phases that had findings]
Phases passed completely:
- [List phases with no issues]
---
Next Steps
Immediate actions (before merge): 1. [Action 1 - usually fixing blockers] 2. [Action 2 - usually fixing high-priority issues]
Example:
1. Fix keyboard accessibility for submit button (Blocker)
2. Improve color contrast on disabled button text (High-priority)
3. Add missing alt text to product images (High-priority)
Follow-up actions (next sprint/PR): 1. [Action 1 - medium-priority improvements] 2. [Action 2 - enhancements]
Example:
1. Standardize card spacing to use design tokens (Medium)
2. Add loading skeleton for async content (Medium)
Optional refinements:
- [List nitpicks that could be addressed if time allows]
Example:
- Consider adding checkmark icon to success messages (Nitpick)
- Adjust button border-radius for consistency (Nitpick)
---
Overall Assessment
[Choose one and explain reasoning:]
✅ Ready to merge - No blocking issues. All critical functionality works correctly. Minor issues can be addressed in follow-up.
⚠️ Ready to merge after blockers fixed - [X] blocking issue(s) must be resolved, then good to merge.
🛑 Needs revisions - Multiple high-priority issues require attention before merge. See findings above.
Reasoning: [1-2 sentences explaining the assessment]
Example (Ready to merge after blockers fixed):
The implementation is solid overall with excellent attention to visual detail and user experience. The keyboard accessibility issue is critical and must be fixed, but once resolved, this is ready to ship. The high-priority contrast issue should also be addressed before merge for WCAG compliance.
---
Reviewer Notes
Reviewer: [Your name or "Claude Code design-review skill"]
Review date: [YYYY-MM-DD]
Time spent: [Approximate time - e.g., "~30 minutes"]
Additional comments: [Any additional context, observations, or recommendations that don't fit the categories above]
Example:
This review focused heavily on accessibility due to the form-heavy nature of the changes. The team has done excellent work maintaining visual consistency with the design system. Consider scheduling a follow-up accessibility audit for the entire checkout flow once these changes are merged.
---
End of Report
---
Template Usage Tips
1. Always start positive - Acknowledge what works well before listing issues 2. Be specific - Include screenshots and exact steps to reproduce 3. Describe impact - Explain why each issue matters to users 4. Triage clearly - Use the Blocker/High/Medium/Nitpick system consistently 5. Provide evidence - Screenshots, console logs, and test results 6. Keep nitpicks optional - Clearly mark subjective preferences as "Nit:" 7. End constructively - Clear next steps and overall assessment
Remember: The goal is to improve the product while maintaining positive collaboration. Focus on problems and impact, not prescriptive solutions.
WCAG 2.1 AA Accessibility Checklist
Standard: Web Content Accessibility Guidelines (WCAG) 2.1 Level AA Target: Inclusive design for users with disabilities Reference: https://www.w3.org/WAI/WCAG21/quickref/?versions=2.1&levels=aa
This comprehensive checklist covers all WCAG 2.1 AA success criteria organized by the four principles: Perceivable, Operable, Understandable, Robust (POUR).
---
Principle 1: Perceivable
Information and user interface components must be presentable to users in ways they can perceive.
1.1 Text Alternatives
1.1.1 Non-text Content (Level A)
Requirement: All non-text content has a text alternative that serves the equivalent purpose.
Testing procedure:
# Check for images without alt text
grep -r '<img' . | grep -v 'alt='
# Verify alt text is descriptive
# - Meaningful images: Describe what the image conveys
# - Decorative images: Use empty alt (alt="")
# - Functional images (buttons, links): Describe functionCommon violations:
<img src="logo.png">- Missing alt attribute<img src="chart.png" alt="image">- Non-descriptive alt text<img src="decoration.svg" alt="Decorative image">- Should bealt=""- Icon buttons without accessible names
How to fix:
<!-- ❌ Bad -->
<img src="logo.png">
<button><img src="trash.svg"></button>
<!-- ✅ Good -->
<img src="logo.png" alt="Company name logo">
<img src="decoration.svg" alt="" role="presentation">
<button aria-label="Delete item"><img src="trash.svg" alt=""></button>---
1.3 Adaptable
1.3.1 Info and Relationships (Level A)
Requirement: Information, structure, and relationships can be programmatically determined.
Testing procedure:
- Verify semantic HTML usage (
<nav>,<main>,<header>,<footer>,<aside>) - Check heading hierarchy (h1 → h2 → h3, no skipping)
- Validate form labels are associated with inputs
- Ensure lists use
<ul>/<ol>+<li>structure - Tables use
<table>,<th>,<caption>appropriately
Common violations:
- Skipping heading levels (h1 → h3)
- Using
<div>instead of semantic elements - Form inputs without associated labels
- Presentational tables missing proper structure
How to fix:
<!-- ❌ Bad: Non-semantic, skipped heading, unassociated label -->
<div class="page-header">
<h1>Dashboard</h1>
<h3>Settings</h3>
</div>
<div>
<span>Email</span>
<input type="email">
</div>
<!-- ✅ Good: Semantic HTML, proper hierarchy, associated labels -->
<header>
<h1>Dashboard</h1>
<h2>Settings</h2>
</header>
<form>
<label for="email">Email</label>
<input type="email" id="email" name="email">
</form>1.3.2 Meaningful Sequence (Level A)
Requirement: Content order makes sense when linearized.
Testing procedure:
- Disable CSS and read page top-to-bottom
- Tab through page - does focus order make sense?
- Use screen reader to verify reading order
Common violations:
- CSS positioning breaks logical flow
- Tab order jumps around page illogically
- Mobile menu appearing before main content in DOM
1.3.4 Orientation (Level AA)
Requirement: Content not restricted to a single display orientation (portrait or landscape).
Testing procedure:
- Rotate device/browser to portrait and landscape
- Verify all content and functionality accessible in both orientations
Common violations:
- Forced landscape orientation with CSS/JS
- Features only work in one orientation
1.3.5 Identify Input Purpose (Level AA)
Requirement: Input fields collecting user information have autocomplete attributes.
Testing procedure:
- Check form inputs have appropriate
autocompleteattributes
How to fix:
<!-- ✅ Good: Autocomplete attributes for common fields -->
<input type="text" name="name" autocomplete="name">
<input type="email" name="email" autocomplete="email">
<input type="tel" name="phone" autocomplete="tel">
<input type="text" name="address" autocomplete="street-address">
<input type="text" name="zip" autocomplete="postal-code">---
1.4 Distinguishable
1.4.3 Contrast (Minimum) (Level AA)
Requirement: Text and images of text have contrast ratio of at least:
- 4.5:1 for normal text
- 3:1 for large text (18pt+ or 14pt+ bold)
Testing procedure: 1. Take screenshots of all text content 2. Use WebAIM Contrast Checker: https://webaim.org/resources/contrastchecker/ 3. Test foreground/background combinations 4. Verify UI components meet 3:1 minimum
Common violations:
- Gray text on gray background (2.5:1 ratio)
- Light text on white background
- Disabled state text too faint (<3:1)
- Placeholder text with poor contrast
- Link text not sufficiently distinct
How to test:
# Using browser DevTools
# 1. Inspect element
# 2. Check computed colors
# 3. Use Lighthouse accessibility audit
# 4. Or use online contrast checkerTriage: [High-Priority] - WCAG AA violations
1.4.4 Resize Text (Level AA)
Requirement: Text can be resized up to 200% without loss of content or functionality.
Testing procedure:
# Browser zoom to 200%
Cmd/Ctrl + Plus (+) to 200%
# Verify:
# - All text remains readable
# - No content hidden or cut off
# - All functionality still worksCommon violations:
- Fixed pixel font sizes that don't scale
- Containers with
overflow: hiddencutting off text - Breakpoints that fail at zoom levels
1.4.5 Images of Text (Level AA)
Requirement: Use actual text rather than images of text (except for logos).
Testing procedure:
- Identify any text rendered as images
- Verify it's necessary (e.g., logo, specific presentation)
Common violations:
- Headings as images instead of styled text
- Buttons using image sprites instead of CSS/SVG
- Decorative text as images
1.4.10 Reflow (Level AA)
Requirement: Content reflows without requiring horizontal scrolling at:
- 320px width for vertical scrolling content
- 256px height for horizontal scrolling content
Testing procedure:
# Resize browser to 320px width
# Zoom to 400%
# Verify no horizontal scrolling requiredCommon violations:
- Fixed-width containers causing horizontal scroll
- Data tables without responsive design
- Wide images not scaling down
1.4.11 Non-text Contrast (Level AA)
Requirement: UI components and graphical objects have contrast ratio of at least 3:1.
Testing procedure:
- Check buttons, form inputs, icons against background
- Verify active/focus states have sufficient contrast
- Test charts and graphs for distinguishability
Common violations:
- Light gray borders on white background
- Subtle icons without sufficient contrast
- Focus indicators too faint (<3:1)
1.4.12 Text Spacing (Level AA)
Requirement: No loss of content when user adjusts text spacing.
Testing procedure:
/* Apply these overrides via browser DevTools */
* {
line-height: 1.5 !important;
letter-spacing: 0.12em !important;
word-spacing: 0.16em !important;
}
p {
margin-bottom: 2em !important;
}
/* Verify content still readable and accessible */Common violations:
- Containers with fixed heights cutting off text
- Overlapping elements when spacing increased
1.4.13 Content on Hover or Focus (Level AA)
Requirement: Additional content appearing on hover/focus must be:
- Dismissible: Can be closed without moving pointer/focus
- Hoverable: Pointer can move over additional content
- Persistent: Remains visible until dismissed
Testing procedure:
- Test all tooltips, dropdowns, popovers
- Verify ESC key dismisses content
- Check if mouse can move to additional content without it disappearing
Common violations:
- Tooltips that disappear immediately when mouse moves
- Hover content with no keyboard dismiss option
- Popovers that can't be accessed by keyboard users
---
Principle 2: Operable
User interface components and navigation must be operable.
2.1 Keyboard Accessible
2.1.1 Keyboard (Level A)
Requirement: All functionality available via keyboard alone.
Testing procedure:
# Disconnect mouse
# Tab through entire page
# Verify:
# - All interactive elements reachable
# - Enter/Space activates buttons and links
# - Arrow keys work in custom controls
# - Escape closes modalsCommon violations:
- Clickable divs without keyboard support
- Custom dropdowns not keyboard navigable
- Drag-and-drop with no keyboard alternative
- Hover-only content
How to fix:
<!-- ❌ Bad: div with onClick, no keyboard support -->
<div onClick={handleClick}>Click me</div>
<!-- ✅ Good: button element, keyboard accessible -->
<button onClick={handleClick}>Click me</button>
<!-- ✅ Good: Custom component with keyboard -->
<div
role="button"
tabIndex={0}
onClick={handleClick}
onKeyDown={(e) => e.key === 'Enter' && handleClick()}
>
Click me
</div>2.1.2 No Keyboard Trap (Level A)
Requirement: Keyboard focus can be moved away from any component.
Testing procedure:
- Tab through page
- Verify never "stuck" in any component
- Check modals allow ESC or Tab to exit
Common violations:
- Modal dialogs trapping focus with no escape
- Custom inputs preventing Tab navigation
- Infinite loops in tab order
2.1.4 Character Key Shortcuts (Level A)
Requirement: Single character shortcuts can be turned off, remapped, or only active on focus.
Testing procedure:
- Identify keyboard shortcuts (especially single letters)
- Verify they can be disabled or customized
2.2 Enough Time
2.2.1 Timing Adjustable (Level A)
Requirement: Time limits can be turned off, adjusted, or extended.
Testing procedure:
- Identify any time limits (session timeouts, auto-advancing carousels)
- Verify user can disable, extend, or get warnings
Common violations:
- 30-second timeout with no warning
- Auto-advancing carousel with no pause button
- Forced redirects without user control
2.2.2 Pause, Stop, Hide (Level A)
Requirement: Moving, blinking, or auto-updating content can be paused, stopped, or hidden.
Testing procedure:
- Find auto-playing videos, carousels, scrolling text
- Verify pause/stop controls present
Common violations:
- Auto-playing video with no pause button
- Carousel with no stop control
- Live-updating content with no pause
2.3 Seizures and Physical Reactions
2.3.1 Three Flashes or Below Threshold (Level A)
Requirement: No content flashes more than three times per second.
Testing procedure:
- Identify any flashing or rapidly changing content
- Verify flashes less than 3 per second
2.4 Navigable
2.4.1 Bypass Blocks (Level A)
Requirement: Mechanism to skip repeated blocks (navigation, headers).
Testing procedure:
- Tab to first interactive element
- Verify "Skip to main content" link present
- Check it focuses main content when activated
How to fix:
<!-- ✅ Good: Skip link (visually hidden until focused) -->
<a href="#main-content" class="skip-link">Skip to main content</a>
<nav>...</nav>
<main id="main-content">...</main>
<style>
.skip-link {
position: absolute;
top: -40px;
left: 0;
background: #000;
color: #fff;
padding: 8px;
z-index: 100;
}
.skip-link:focus {
top: 0;
}
</style>2.4.2 Page Titled (Level A)
Requirement: Web pages have descriptive and unique titles.
Testing procedure:
- Check
<title>element exists - Verify title describes page purpose
- Ensure titles unique across site
Common violations:
- Missing or empty
<title> - Generic titles ("Dashboard" on every page)
- Title doesn't reflect page content
2.4.3 Focus Order (Level A)
Requirement: Focusable components receive focus in logical order.
Testing procedure:
- Tab through page
- Verify focus moves in reading order (left-to-right, top-to-bottom)
- Check no illogical jumps
Common violations:
- Tab order jumps to footer before main content
- Focus moves backwards unexpectedly
- CSS positioning breaks DOM order
2.4.4 Link Purpose (In Context) (Level A)
Requirement: Purpose of each link can be determined from link text or context.
Testing procedure:
- Read all link text out of context
- Verify each link's purpose is clear
Common violations:
- Multiple "Click here" or "Read more" links
- Generic "Learn more" without context
- Links without text (icon-only)
How to fix:
<!-- ❌ Bad: Generic link text -->
<a href="/article1">Click here</a> for more information.
<!-- ✅ Good: Descriptive link text -->
<a href="/article1">Read the full article about design systems</a>
<!-- ✅ Good: Icon button with aria-label -->
<a href="/article1" aria-label="Read article about design systems">
<svg>...</svg>
</a>2.4.5 Multiple Ways (Level AA)
Requirement: Multiple ways to locate pages (navigation, search, sitemap).
Testing procedure:
- Verify navigation menu present
- Check for search functionality
- Verify sitemap or alternative navigation method
2.4.6 Headings and Labels (Level AA)
Requirement: Headings and labels describe topic or purpose.
Testing procedure:
- Review all headings and form labels
- Verify they clearly describe content
Common violations:
- Generic headings like "Content" or "Information"
- Form labels like "Field 1" instead of "Email address"
2.4.7 Focus Visible (Level AA)
Requirement: Keyboard focus indicator is visible.
Testing procedure:
# Tab through entire page
# Verify every interactive element shows visible focus indicator
# - Outline, border, background change, or glow
# - Must be clearly visible (contrast 3:1 minimum)Common violations:
outline: nonewith no alternative focus style- Focus indicator too subtle (light gray border)
- No focus indicator on custom components
How to fix:
/* ❌ Bad: Removes focus with no alternative */
button:focus {
outline: none;
}
/* ✅ Good: Custom focus indicator */
button:focus {
outline: 2px solid #4A90E2;
outline-offset: 2px;
}
/* ✅ Good: Visible focus with contrast */
button:focus-visible {
box-shadow: 0 0 0 3px rgba(74, 144, 226, 0.5);
}---
Principle 3: Understandable
Information and user interface operation must be understandable.
3.1 Readable
3.1.1 Language of Page (Level A)
Requirement: Default human language of page is programmatically determined.
Testing procedure:
<!-- ✅ Verify <html> has lang attribute -->
<html lang="en">3.1.2 Language of Parts (Level AA)
Requirement: Language of passages or phrases can be programmatically determined.
Testing procedure:
<!-- ✅ Mark foreign language content -->
<p>The French phrase <span lang="fr">mise en place</span> means "putting in place".</p>3.2 Predictable
3.2.1 On Focus (Level A)
Requirement: Receiving focus does not initiate a change of context.
Testing procedure:
- Tab through page
- Verify no unexpected actions on focus (page redirects, modal opens, form submits)
Common violations:
- Form submits when last field receives focus
- Dropdown opens automatically on focus (without user action)
3.2.2 On Input (Level A)
Requirement: Changing input settings does not cause unexpected change of context.
Testing procedure:
- Interact with all form controls
- Verify no automatic submissions or navigation
Common violations:
- Form auto-submits when dropdown changed
- Page redirects when checkbox checked
- Modal opens when radio button selected
3.2.3 Consistent Navigation (Level AA)
Requirement: Navigation mechanisms repeated on multiple pages occur in same relative order.
Testing procedure:
- Navigate between pages
- Verify navigation menu in same location and order
3.2.4 Consistent Identification (Level AA)
Requirement: Components with same functionality are identified consistently.
Testing procedure:
- Find repeated components (search button, login link)
- Verify same labels and icons used consistently
Common violations:
- "Sign in" on homepage, "Log in" on other pages
- Search icon different across pages
3.3 Input Assistance
3.3.1 Error Identification (Level A)
Requirement: Input errors are identified and described in text.
Testing procedure:
- Submit forms with invalid data
- Verify clear error messages
- Check errors described in text (not just red border)
Common violations:
- Red border only (no text explanation)
- Generic error ("Invalid input")
- Error not programmatically associated with input
How to fix:
<!-- ✅ Good: Error associated with input -->
<label for="email">Email</label>
<input
type="email"
id="email"
aria-invalid="true"
aria-describedby="email-error"
>
<span id="email-error" class="error">Please enter a valid email address</span>3.3.2 Labels or Instructions (Level A)
Requirement: Labels or instructions provided when content requires user input.
Testing procedure:
- Check all form inputs have labels
- Verify required fields marked
- Ensure format instructions provided (e.g., "MM/DD/YYYY")
Common violations:
- Inputs with placeholder only (no label)
- Required fields not indicated
- Expected format not explained
3.3.3 Error Suggestion (Level AA)
Requirement: Suggestions for correcting input errors are provided.
Testing procedure:
- Submit form with errors
- Verify error messages include guidance
Common violations:
- "Invalid password" (no hint about requirements)
- "Date format error" (no format shown)
How to fix:
<!-- ✅ Good: Helpful error with suggestion -->
<span id="password-error" class="error">
Password must be at least 8 characters and include a number.
</span>3.3.4 Error Prevention (Legal, Financial, Data) (Level AA)
Requirement: Submissions that cause legal/financial commitments are:
- Reversible, or
- Checked for errors, or
- Confirmed before submission
Testing procedure:
- Test purchase/delete/submit flows
- Verify confirmation step or ability to review/edit
Common violations:
- Delete button with no confirmation
- Purchase with no review step
- Data submission with no preview
---
Principle 4: Robust
Content must be robust enough to be interpreted by a wide variety of user agents, including assistive technologies.
4.1 Compatible
4.1.1 Parsing (Level A)
Requirement: HTML markup is valid and properly nested.
Testing procedure:
# Use W3C HTML Validator
# https://validator.w3.org/
# Check for:
# - Properly closed tags
# - No duplicate IDs
# - Valid attribute values4.1.2 Name, Role, Value (Level A)
Requirement: For all UI components:
- Name can be programmatically determined
- Role can be programmatically determined
- States/properties can be programmatically set
Testing procedure:
- Inspect custom components
- Verify appropriate ARIA attributes
- Test with screen reader
Common violations:
- Custom checkbox without
role="checkbox"andaria-checked - Expandable sections without
aria-expanded - Toggle buttons without state indication
How to fix:
<!-- ✅ Good: Custom checkbox with ARIA -->
<div
role="checkbox"
aria-checked="false"
aria-labelledby="checkbox-label"
tabindex="0"
>
<span id="checkbox-label">Agree to terms</span>
</div>
<!-- ✅ Good: Expandable section -->
<button aria-expanded="false" aria-controls="details">
Show details
</button>
<div id="details" hidden>...</div>4.1.3 Status Messages (Level AA)
Requirement: Status messages can be programmatically determined through role or properties.
Testing procedure:
- Test success messages, error alerts, progress notifications
- Verify
role="status",role="alert", oraria-liveused
Common violations:
- Toast notifications without ARIA live regions
- Success messages not announced to screen readers
- Loading states not programmatically indicated
How to fix:
<!-- ✅ Good: Live region for status messages -->
<div role="status" aria-live="polite">
Your changes have been saved.
</div>
<!-- ✅ Good: Alert for errors -->
<div role="alert" aria-live="assertive">
Error: Unable to process payment.
</div>---
Testing Tools
Automated Tools
1. Lighthouse (Chrome DevTools)
- Built into Chrome DevTools
- Comprehensive accessibility audit
- Provides specific issues and recommendations
2. axe DevTools (Browser Extension)
- Free browser extension
- Catches ~57% of WCAG issues automatically
- Detailed violation explanations
3. WAVE (WebAIM)
- Browser extension and online tool
- Visual feedback on accessibility
- https://wave.webaim.org/
4. Pa11y (Command Line)
npm install -g pa11y
pa11y https://your-site.comManual Testing Tools
1. WebAIM Contrast Checker
- https://webaim.org/resources/contrastchecker/
- Test foreground/background color combinations
2. Keyboard Only Navigation
- Disconnect mouse
- Tab through entire interface
- Verify all functionality accessible
3. Screen Readers
- macOS: VoiceOver (Cmd+F5)
- Windows: NVDA (free) or JAWS
- Mobile: VoiceOver (iOS), TalkBack (Android)
4. Browser Zoom
- Test at 200% zoom
- Verify reflow without horizontal scrolling
---
Quick Reference: Most Common Violations
Based on WebAIM Million Report, these are the most common accessibility issues:
| Issue | Percentage | WCAG Criterion | Fix |
|---|---|---|---|
| Low contrast text | 86.4% | 1.4.3 | Ensure 4.5:1 minimum |
| Missing alt text | 55.4% | 1.1.1 | Add descriptive alt attributes |
| Empty links | 50.7% | 2.4.4 | Provide link text or aria-label |
| Missing form labels | 46.1% | 3.3.2 | Associate label with input |
| Empty buttons | 28.2% | 4.1.2 | Provide button text or aria-label |
| Missing document language | 22.1% | 3.1.1 | Add lang="en" to <html> |
---
Triage Priorities
[Blocker] - Critical WCAG violations that prevent access:
- No keyboard access to core functionality
- Critical color contrast failures (<3:1)
- Missing form labels on required inputs
- Keyboard traps
[High-Priority] - WCAG AA violations that impact experience:
- Poor contrast (3:1 to 4.4:1 for text)
- Missing focus indicators
- Unlabeled interactive elements
- Non-semantic HTML breaking screen readers
[Medium-Priority] - Violations that affect some users:
- Minor semantic HTML issues
- Missing skip links
- Inconsistent navigation
- Generic link text ("Click here")
[Nitpick] - AAA or enhanced accessibility:
- Contrast ratios above 7:1 (AAA level)
- Additional ARIA landmarks
- Enhanced keyboard shortcuts
---
For questions on specific WCAG criteria, see the official quick reference: https://www.w3.org/WAI/WCAG21/quickref/?versions=2.1&levels=aa
Browser Tools Reference for Design Reviews
Purpose: Quick reference for browser automation tools used in design reviews Tools: Playwright MCP (recommended) and Chrome DevTools CLI (alternative)
---
Tool Selection
Playwright MCP (Recommended)
Best for:
- Interactive testing (clicks, typing, navigation)
- Keyboard navigation testing
- Form interaction testing
- Complete design reviews with UX testing
See the `playwright-testing` skill for:
- Complete Playwright MCP installation guide
- Configuration and setup
- Advanced testing patterns
- End-to-end test examples
Chrome DevTools CLI (Alternative)
Best for:
- Screenshot capture
- Performance analysis
- Network monitoring
- Visual QA and simpler reviews
See the `chrome-devtools` skill for:
- Puppeteer CLI installation and setup
- System dependencies (Linux/WSL)
- Screenshot automation scripts
- Performance auditing tools
---
Playwright MCP Commands
For complete Playwright documentation, see the playwright-testing skill.
Prerequisites Check
# Verify Playwright MCP is available
# Should see Playwright tools in MCP tool listNavigation
Navigate to URL:
mcp__playwright__browser_navigate(url: "https://preview.example.com")Navigation controls:
# Go back
mcp__playwright__browser_navigate_back()
# Go forward
mcp__playwright__browser_navigate_forward()Viewport Testing (Responsive Design)
Desktop (1440px):
mcp__playwright__browser_resize(width: 1440, height: 900)
mcp__playwright__browser_take_screenshot(fullPage: true)Tablet (768px):
mcp__playwright__browser_resize(width: 768, height: 1024)
mcp__playwright__browser_take_screenshot(fullPage: true)Mobile (375px):
mcp__playwright__browser_resize(width: 375, height: 667)
mcp__playwright__browser_take_screenshot(fullPage: true)Screenshots
Full page screenshot:
mcp__playwright__browser_take_screenshot(fullPage: true)Specific element screenshot:
mcp__playwright__browser_take_screenshot(
selector: ".component-class",
fullPage: false
)With custom options:
mcp__playwright__browser_take_screenshot(
fullPage: true,
type: "png", # or "jpeg"
quality: 90 # for jpeg only
)Interaction Testing
Click element:
mcp__playwright__browser_click(selector: "button.submit")
# With options
mcp__playwright__browser_click(
selector: "button.submit",
timeout: 5000,
force: false # respect visibility checks
)Type in input:
mcp__playwright__browser_type(
selector: "input[name='email']",
text: "test@example.com"
)
# With delay (for testing animations)
mcp__playwright__browser_type(
selector: "input[name='email']",
text: "test@example.com",
delay: 100 # milliseconds between keystrokes
)Hover over element:
mcp__playwright__browser_hover(selector: ".card:first-child")Select from dropdown:
mcp__playwright__browser_select_option(
selector: "select#country",
value: "US" # or label: "United States"
)Press keyboard key:
# Press Enter
mcp__playwright__browser_press_key(key: "Enter")
# Press Tab (for focus testing)
mcp__playwright__browser_press_key(key: "Tab")
# Press Escape
mcp__playwright__browser_press_key(key: "Escape")
# Key combinations
mcp__playwright__browser_press_key(key: "Control+A")Form Testing
Upload file:
mcp__playwright__browser_file_upload(
selector: "input[type='file']",
filePath: "/path/to/test-image.png"
)Drag and drop:
mcp__playwright__browser_drag(
sourceSelector: ".draggable-item",
targetSelector: ".drop-zone"
)Console & Network Monitoring
Check console messages:
mcp__playwright__browser_console_messages()Returns JavaScript console logs, warnings, and errors.
Check network requests:
mcp__playwright__browser_network_requests()Returns all network requests made by the page (useful for checking API calls).
Wait for Elements
Wait for element to appear:
mcp__playwright__browser_wait_for(
selector: ".loading-spinner",
state: "hidden", # Wait for spinner to disappear
timeout: 5000
)
# Or wait for element to appear
mcp__playwright__browser_wait_for(
selector: ".success-message",
state: "visible",
timeout: 5000
)Wait states:
visible- Wait for element to be visiblehidden- Wait for element to be hiddenattached- Wait for element in DOMdetached- Wait for element to be removed
DOM Inspection
Get page snapshot:
mcp__playwright__browser_snapshot()Returns simplified DOM structure with accessibility tree.
Evaluate JavaScript:
mcp__playwright__browser_evaluate(expression: "document.title")
# Get computed styles
mcp__playwright__browser_evaluate(
expression: "getComputedStyle(document.querySelector('.button')).color"
)
# Check element properties
mcp__playwright__browser_evaluate(
expression: "document.querySelector('input[name=\"email\"]').value"
)Dialog Handling
Handle alerts/confirms:
mcp__playwright__browser_handle_dialog(
accept: true, # Accept dialog
promptText: "" # Text for prompt dialogs
)Tab Management
List open tabs:
mcp__playwright__browser_tab_list()Open new tab:
mcp__playwright__browser_tab_new(url: "https://example.com")Switch to tab:
mcp__playwright__browser_tab_select(tabId: "tab-id-from-list")Close tab:
mcp__playwright__browser_tab_close(tabId: "tab-id-from-list")Browser Management
Install browsers:
mcp__playwright__browser_install()Close browser:
mcp__playwright__browser_close()---
Chrome DevTools CLI Scripts
For complete Chrome DevTools documentation, see the chrome-devtools skill.
Prerequisites Check
# Check if Chrome DevTools scripts available
ls ~/.claude/skills/chrome-devtools/scripts/
# Verify Node dependencies installed
cd ~/.claude/skills/chrome-devtools/scripts
bun install # or npm installScreenshot Capture
Basic screenshot:
cd ~/.claude/skills/chrome-devtools/scripts
node screenshot.js --url "https://preview.example.com" --output "./screenshot.png"Full page screenshot:
node screenshot.js \
--url "https://preview.example.com" \
--output "./screenshot.png" \
--fullPageCustom viewport:
# Mobile viewport
node screenshot.js \
--url "https://preview.example.com" \
--output "./mobile.png" \
--width 375 \
--height 667
# Tablet viewport
node screenshot.js \
--url "https://preview.example.com" \
--output "./tablet.png" \
--width 768 \
--height 1024
# Desktop viewport
node screenshot.js \
--url "https://preview.example.com" \
--output "./desktop.png" \
--width 1440 \
--height 900Performance Analysis
Run performance audit:
node performance.js \
--url "https://preview.example.com" \
--output "./perf-report.json"Returns metrics:
- First Contentful Paint (FCP)
- Largest Contentful Paint (LCP)
- Time to Interactive (TTI)
- Total Blocking Time (TBT)
- Cumulative Layout Shift (CLS)
Network Monitoring
Capture network requests:
node network.js \
--url "https://preview.example.com" \
--output "./network-log.json"Returns:
- All HTTP requests
- Request/response headers
- Timing information
- Status codes
---
Selector Strategies
CSS Selectors (Recommended)
By ID:
selector: "#submit-button"By class:
selector: ".primary-button"By attribute:
selector: "button[type='submit']"
selector: "input[name='email']"
selector: "a[href='/about']"Combinators:
# Child selector
selector: "form > button"
# Descendant selector
selector: "nav a"
# Adjacent sibling
selector: ".error + .help-text"
# Multiple classes
selector: ".button.primary"Pseudo-classes:
# First child
selector: "li:first-child"
# Last child
selector: "li:last-child"
# Nth child
selector: "li:nth-child(2)"
# Hover (use browser_hover instead)
selector: "button:hover"Text Content Selectors
Playwright text selectors:
# By exact text
selector: "text=Submit"
# By partial text
selector: "text=/Submit.*/"
# Button with specific text
selector: "button:has-text('Submit')"Accessibility Selectors (Playwright)
By role:
# Button role
selector: "role=button[name='Submit']"
# Link role
selector: "role=link[name='Home']"
# Textbox role
selector: "role=textbox[name='Email']"By label:
selector: "label:has-text('Email') + input"---
Common Testing Workflows
Workflow 1: Complete Responsive Review
# 1. Navigate to preview
mcp__playwright__browser_navigate(url: "https://preview.example.com")
# 2. Desktop screenshot
mcp__playwright__browser_resize(width: 1440, height: 900)
mcp__playwright__browser_take_screenshot(fullPage: true)
# 3. Tablet screenshot
mcp__playwright__browser_resize(width: 768, height: 1024)
mcp__playwright__browser_take_screenshot(fullPage: true)
# 4. Mobile screenshot
mcp__playwright__browser_resize(width: 375, height: 667)
mcp__playwright__browser_take_screenshot(fullPage: true)
# 5. Check console for errors
mcp__playwright__browser_console_messages()Workflow 2: Form Interaction Testing
# 1. Navigate to form page
mcp__playwright__browser_navigate(url: "https://preview.example.com/contact")
# 2. Fill out form
mcp__playwright__browser_type(
selector: "input[name='name']",
text: "John Doe"
)
mcp__playwright__browser_type(
selector: "input[name='email']",
text: "john@example.com"
)
mcp__playwright__browser_type(
selector: "textarea[name='message']",
text: "This is a test message"
)
# 3. Submit form
mcp__playwright__browser_click(selector: "button[type='submit']")
# 4. Wait for success message
mcp__playwright__browser_wait_for(
selector: ".success-message",
state: "visible"
)
# 5. Take screenshot of success state
mcp__playwright__browser_take_screenshot()Workflow 3: Keyboard Navigation Testing
# 1. Navigate to page
mcp__playwright__browser_navigate(url: "https://preview.example.com")
# 2. Tab through interactive elements
mcp__playwright__browser_press_key(key: "Tab")
mcp__playwright__browser_take_screenshot() # Verify focus visible
mcp__playwright__browser_press_key(key: "Tab")
mcp__playwright__browser_take_screenshot() # Next element
# Repeat for all interactive elements
# 3. Activate focused element
mcp__playwright__browser_press_key(key: "Enter")
# 4. Test modal keyboard handling
mcp__playwright__browser_press_key(key: "Escape") # Close modalWorkflow 4: Interactive State Testing
# 1. Navigate to page
mcp__playwright__browser_navigate(url: "https://preview.example.com")
# 2. Test hover state
mcp__playwright__browser_hover(selector: ".card:first-child")
mcp__playwright__browser_take_screenshot() # Capture hover state
# 3. Test focus state
mcp__playwright__browser_click(selector: "button.primary")
# (Focus happens automatically on click)
mcp__playwright__browser_take_screenshot() # Capture focus state
# 4. Test active/pressed state
# (Requires quick screenshot during click - challenging)
# 5. Test disabled state
# (Check existing disabled elements)
mcp__playwright__browser_take_screenshot(selector: "button:disabled")---
Troubleshooting
Playwright MCP Issues
Problem: Playwright MCP commands not available
Solution: 1. Check if Playwright MCP server is running 2. Verify MCP configuration in Claude Code settings 3. See playwright-testing skill for installation guide
Problem: Selector not finding element
Solution:
# Use browser_snapshot to see available elements
mcp__playwright__browser_snapshot()
# Try different selector strategies:
# - CSS: "#id", ".class", "tag[attr='value']"
# - Text: "text=exact text" or "text=/regex/"
# - Role: "role=button[name='Submit']"Problem: Timeout waiting for element
Solution:
# Increase timeout
mcp__playwright__browser_wait_for(
selector: ".slow-element",
timeout: 10000 # 10 seconds instead of default 5
)
# Or wait for network idle
mcp__playwright__browser_wait_for(
selector: ".dynamic-content",
state: "visible"
)Chrome DevTools Issues
Problem: Chrome dependencies missing (Linux/WSL)
Solution:
cd ~/.claude/skills/chrome-devtools/scripts
./install-deps.sh # Auto-installs system dependenciesProblem: Screenshot file too large
Solution:
# Chrome DevTools auto-compresses with ImageMagick if installed
# Install ImageMagick:
brew install imagemagick # macOS
sudo apt install imagemagick # Ubuntu/DebianSee chrome-devtools skill for complete troubleshooting guide.
---
Quick Reference Card
| Task | Playwright MCP | Chrome DevTools CLI |
|---|---|---|
| Screenshot | browser_take_screenshot() | node screenshot.js --url URL |
| Resize viewport | browser_resize(width, height) | --width 375 --height 667 |
| Click element | browser_click(selector) | N/A (use Playwright) |
| Type text | browser_type(selector, text) | N/A (use Playwright) |
| Check console | browser_console_messages() | N/A (use Playwright) |
| Performance | N/A (use Chrome DevTools) | node performance.js --url URL |
---
Tool Installation
Playwright MCP
See the `playwright-testing` skill for complete installation instructions:
- MCP server configuration
- Browser installation
- TypeScript/JavaScript setup
- Configuration examples
Chrome DevTools CLI
See the `chrome-devtools` skill for complete installation instructions:
- System dependencies (Linux/WSL)
- Node.js/Bun setup
- Puppeteer installation
- ImageMagick (optional, for compression)
- Script usage examples
---
Additional Resources
- Playwright Documentation: https://playwright.dev/
- Puppeteer Documentation: https://pptr.dev/
- Chrome DevTools Protocol: https://chromedevtools.github.io/devtools-protocol/
---
For design review purposes, Playwright MCP is recommended for its interactive testing capabilities. Use Chrome DevTools CLI as a fallback for simpler visual testing tasks.
Code Health Patterns & Examples
Purpose: Detailed code examples and patterns for evaluating code health during design reviews Related: SKILL.md Phase 6 - Code Health
---
Component Reuse Patterns
The DRY Principle in Components
Bad: Copy-pasted components with minor variations
// ❌ File: UserCard.tsx
export function UserCard({ name, email }) {
return (
<div className="border rounded p-4 shadow">
<h3 className="text-lg font-bold">{name}</h3>
<p className="text-sm text-gray-600">{email}</p>
</div>
);
}
// ❌ File: ProductCard.tsx
export function ProductCard({ title, price }) {
return (
<div className="border rounded p-4 shadow">
<h3 className="text-lg font-bold">{title}</h3>
<p className="text-sm text-gray-600">${price}</p>
</div>
);
}Good: Extracted shared Card component
// ✅ File: Card.tsx
export function Card({ title, subtitle, children }) {
return (
<div className="border rounded p-4 shadow">
{title && <h3 className="text-lg font-bold">{title}</h3>}
{subtitle && <p className="text-sm text-gray-600">{subtitle}</p>}
{children}
</div>
);
}
// ✅ File: UserCard.tsx
export function UserCard({ name, email }) {
return <Card title={name} subtitle={email} />;
}
// ✅ File: ProductCard.tsx
export function ProductCard({ title, price }) {
return <Card title={title} subtitle={`$${price}`} />;
}---
Design Token Usage
Color Tokens
Bad: Hardcoded color values
/* ❌ Hardcoded hex values scattered throughout */
.button-primary {
background-color: #3b82f6;
color: #ffffff;
}
.button-secondary {
background-color: #6b7280;
color: #ffffff;
}
.error-text {
color: #ef4444;
}
.success-text {
color: #10b981;
}Good: CSS variables / design tokens
/* ✅ Define tokens once */
:root {
--color-primary-600: #3b82f6;
--color-gray-600: #6b7280;
--color-error-600: #ef4444;
--color-success-600: #10b981;
--color-white: #ffffff;
}
/* ✅ Use tokens everywhere */
.button-primary {
background-color: var(--color-primary-600);
color: var(--color-white);
}
.button-secondary {
background-color: var(--color-gray-600);
color: var(--color-white);
}
.error-text {
color: var(--color-error-600);
}
.success-text {
color: var(--color-success-600);
}Tailwind CSS approach (also good):
<!-- ✅ Tailwind uses design tokens under the hood -->
<button class="bg-primary-600 text-white">Primary</button>
<button class="bg-gray-600 text-white">Secondary</button>
<p class="text-error-600">Error message</p>
<p class="text-success-600">Success message</p>---
Spacing Tokens
Bad: Magic number spacing
/* ❌ Random pixel values with no system */
.card {
padding: 17px;
margin-bottom: 23px;
}
.section {
margin-top: 35px;
padding: 14px 19px;
}
.list-item {
margin-bottom: 11px;
}Good: 8-point grid system
/* ✅ Define spacing scale (8px base) */
:root {
--space-1: 4px; /* 0.5 × base */
--space-2: 8px; /* 1 × base */
--space-3: 12px; /* 1.5 × base */
--space-4: 16px; /* 2 × base */
--space-6: 24px; /* 3 × base */
--space-8: 32px; /* 4 × base */
}
/* ✅ Use spacing tokens */
.card {
padding: var(--space-4); /* 16px */
margin-bottom: var(--space-6); /* 24px */
}
.section {
margin-top: var(--space-8); /* 32px */
padding: var(--space-4); /* 16px */
}
.list-item {
margin-bottom: var(--space-3); /* 12px */
}Tailwind CSS approach:
<!-- ✅ Tailwind's spacing scale (4px base) -->
<div class="p-4 mb-6">Card</div> <!-- 16px padding, 24px margin-bottom -->
<div class="mt-8 p-4">Section</div> <!-- 32px margin-top, 16px padding -->
<li class="mb-3">List item</li> <!-- 12px margin-bottom -->---
Typography Tokens
Bad: Inconsistent font sizing
/* ❌ Random font sizes */
h1 { font-size: 31px; font-weight: 700; }
h2 { font-size: 23px; font-weight: 650; }
h3 { font-size: 19px; font-weight: 600; }
body { font-size: 15px; }
.caption { font-size: 13px; }Good: Type scale system
/* ✅ Define type scale */
:root {
--text-xs: 12px;
--text-sm: 14px;
--text-base: 16px;
--text-lg: 18px;
--text-xl: 20px;
--text-2xl: 24px;
--text-3xl: 30px;
--text-4xl: 36px;
--font-normal: 400;
--font-medium: 500;
--font-semibold: 600;
--font-bold: 700;
}
/* ✅ Use type scale */
h1 { font-size: var(--text-4xl); font-weight: var(--font-bold); }
h2 { font-size: var(--text-2xl); font-weight: var(--font-semibold); }
h3 { font-size: var(--text-xl); font-weight: var(--font-semibold); }
body { font-size: var(--text-base); font-weight: var(--font-normal); }
.caption { font-size: var(--text-sm); }---
Border Radius Tokens
Bad: Inconsistent rounding
/* ❌ Random border-radius values */
.button { border-radius: 7px; }
.card { border-radius: 9px; }
.input { border-radius: 5px; }
.modal { border-radius: 11px; }Good: Consistent radius scale
/* ✅ Define radius scale */
:root {
--radius-sm: 4px;
--radius-md: 8px;
--radius-lg: 12px;
--radius-xl: 16px;
--radius-full: 9999px;
}
/* ✅ Use radius tokens */
.button { border-radius: var(--radius-md); } /* 8px */
.card { border-radius: var(--radius-lg); } /* 12px */
.input { border-radius: var(--radius-md); } /* 8px */
.modal { border-radius: var(--radius-lg); } /* 12px */---
Pattern Consistency
Naming Conventions
Bad: Inconsistent naming
// ❌ Mixed naming styles
const UserData = { ... };
const product_info = { ... };
const OrderDetails = { ... };
function FetchUser() { ... }
function get_products() { ... }
function loadOrderData() { ... }Good: Consistent conventions
// ✅ Consistent camelCase for variables/functions
const userData = { ... };
const productInfo = { ... };
const orderDetails = { ... };
function fetchUser() { ... }
function getProducts() { ... }
function loadOrderData() { ... }
// ✅ Consistent PascalCase for components
function UserCard() { ... }
function ProductList() { ... }
function OrderSummary() { ... }---
File Structure Consistency
Bad: Inconsistent organization
src/
├── UserProfile.tsx
├── components/ProductCard.tsx
├── OrderDetails.tsx
├── comp/ReviewList.tsx
└── forms/CheckoutForm.tsxGood: Consistent structure
src/
├── components/
│ ├── UserProfile.tsx
│ ├── ProductCard.tsx
│ ├── OrderDetails.tsx
│ ├── ReviewList.tsx
│ └── CheckoutForm.tsx
├── hooks/
│ ├── useUser.ts
│ └── useProducts.ts
└── utils/
└── api.ts---
API Pattern Consistency
Bad: Mixed API patterns
// ❌ Inconsistent patterns
async function getUser(id: string) {
const res = await fetch(`/api/users/${id}`);
return res.json();
}
function fetchProducts() {
return fetch('/api/products').then(r => r.json());
}
const loadOrders = (userId) => {
fetch(`/api/orders?user=${userId}`)
.then(response => response.json())
.then(data => setOrders(data));
};Good: Consistent API pattern
// ✅ Consistent async/await pattern
async function getUser(id: string) {
const response = await fetch(`/api/users/${id}`);
return response.json();
}
async function getProducts() {
const response = await fetch('/api/products');
return response.json();
}
async function getOrders(userId: string) {
const response = await fetch(`/api/orders?user=${userId}`);
return response.json();
}---
Inline Styles vs. Classes
Bad: Inline styles with hardcoded values
// ❌ Inline styles break design system
<div style={{
padding: '17px',
backgroundColor: '#f0f0f0',
borderRadius: '7px',
marginBottom: '23px'
}}>
Content
</div>Good: Classes with design tokens
// ✅ CSS classes use design system
<div className="p-4 bg-gray-100 rounded-md mb-6">
Content
</div>
// Or with CSS modules
<div className={styles.card}>
Content
</div>
// styles.module.css
.card {
padding: var(--space-4);
background-color: var(--color-gray-100);
border-radius: var(--radius-md);
margin-bottom: var(--space-6);
}---
CSS-in-JS with Tokens
Bad: Hardcoded values in styled-components
// ❌ Hardcoded values
const Button = styled.button`
background-color: #3b82f6;
color: #ffffff;
padding: 12px 24px;
border-radius: 8px;
font-size: 16px;
`;Good: Design tokens in styled-components
// ✅ Use theme tokens
const Button = styled.button`
background-color: ${props => props.theme.colors.primary[600]};
color: ${props => props.theme.colors.white};
padding: ${props => props.theme.spacing[3]} ${props => props.theme.spacing[6]};
border-radius: ${props => props.theme.radii.md};
font-size: ${props => props.theme.fontSizes.base};
`;
// Or with CSS variables
const Button = styled.button`
background-color: var(--color-primary-600);
color: var(--color-white);
padding: var(--space-3) var(--space-6);
border-radius: var(--radius-md);
font-size: var(--text-base);
`;---
Red Flags to Look For
1. Duplication
// 🚩 Nearly identical functions
function formatUserName(user) {
return `${user.firstName} ${user.lastName}`;
}
function formatEmployeeName(employee) {
return `${employee.firstName} ${employee.lastName}`;
}
// ✅ Extract shared logic
function formatFullName(person: { firstName: string; lastName: string }) {
return `${person.firstName} ${person.lastName}`;
}2. Magic Numbers
/* 🚩 What do these numbers mean? */
.container {
max-width: 1247px;
padding: 17px 23px;
margin-top: 41px;
}
/* ✅ Self-documenting with tokens */
.container {
max-width: var(--container-max-width); /* or 1200px */
padding: var(--space-4) var(--space-6); /* 16px 24px */
margin-top: var(--space-10); /* 40px */
}3. Inconsistent State Management
// 🚩 Mixed state management approaches
const [user, setUser] = useState(); // React state
const products = useAtom(productsAtom); // Jotai
const orders = useSelector(state => state.orders); // Redux
// ✅ Consistent approach
const [user, setUser] = useState();
const [products, setProducts] = useState();
const [orders, setOrders] = useState();
// Or all in Redux, or all in Zustand, etc.4. Broken Abstraction
// 🚩 Leaky abstraction - component knows too much
function UserCard({ userId }) {
const [user, setUser] = useState(null);
useEffect(() => {
fetch(`https://api.example.com/users/${userId}`)
.then(r => r.json())
.then(setUser);
}, [userId]);
return <div>{user?.name}</div>;
}
// ✅ Proper abstraction - component focused on UI
function UserCard({ user }) {
return <div>{user.name}</div>;
}
// Data fetching handled by parent or hook
function UserProfile({ userId }) {
const user = useUser(userId); // Custom hook handles fetching
return <UserCard user={user} />;
}---
Checklist for Code Health Review
Component Reuse
- [ ] No nearly-identical components in different files
- [ ] Shared components extracted to common location
- [ ] Component composition used appropriately
- [ ] Props used for variation, not duplication
Design Tokens
- [ ] Colors use CSS variables or design system tokens
- [ ] Spacing follows consistent scale (e.g., 8px grid)
- [ ] Typography uses type scale
- [ ] Border radii consistent
- [ ] No magic numbers (random pixel values)
Pattern Consistency
- [ ] Naming conventions consistent (camelCase vs PascalCase)
- [ ] File structure follows project conventions
- [ ] API calls use same pattern throughout
- [ ] State management approach consistent
- [ ] Import order and grouping consistent
Abstraction Quality
- [ ] Components have single responsibility
- [ ] No leaky abstractions (components don't know too much)
- [ ] Appropriate separation of concerns
- [ ] Clear interfaces between layers
---
Triage Priorities
[High] - Introduces technical debt or breaks patterns:
- Copy-pasted components with no extraction
- Hardcoded values that should use design tokens
- Inconsistent patterns that will spread
- Broken abstractions that couple unrelated concerns
[Medium] - Missed opportunities or minor inconsistencies:
- Could extract shared component but not critical
- Uses design tokens inconsistently
- Naming slightly off from conventions
- File organization suboptimal
[Nitpick] - Code style preferences:
- Prefer different variable name
- Could simplify but current code works
- Personal style preferences
- Minor organizational suggestions
---
Tools for Code Health
Linters
- ESLint: Enforce consistent code style
- Prettier: Auto-format code consistently
- StyleLint: CSS/SCSS consistency
Design Token Validation
- Design Lint (Figma): Check design token usage
- Style Dictionary: Build design tokens
- Theo (Salesforce): Transform design tokens
Code Quality
- SonarQube: Code quality and duplication detection
- CodeClimate: Maintainability analysis
- Storybook: Component isolation and testing
---
For complete Code Health review procedures, return to [../SKILL.md Phase 6](../SKILL.md#phase-6-code-health).
S-Tier SaaS Dashboard Design Checklist (Inspired by Stripe, Airbnb, Linear)
I. Core Design Philosophy & Strategy
- [ ] Users First: Prioritize user needs, workflows, and ease of use in every design decision.
- [ ] Meticulous Craft: Aim for precision, polish, and high quality in every UI element and interaction.
- [ ] Speed & Performance: Design for fast load times and snappy, responsive interactions.
- [ ] Simplicity & Clarity: Strive for a clean, uncluttered interface. Ensure labels, instructions, and information are unambiguous.
- [ ] Focus & Efficiency: Help users achieve their goals quickly and with minimal friction. Minimize unnecessary steps or distractions.
- [ ] Consistency: Maintain a uniform design language (colors, typography, components, patterns) across the entire dashboard.
- [ ] Accessibility (WCAG AA+): Design for inclusivity. Ensure sufficient color contrast, keyboard navigability, and screen reader compatibility.
- [ ] Opinionated Design (Thoughtful Defaults): Establish clear, efficient default workflows and settings, reducing decision fatigue for users.
II. Design System Foundation (Tokens & Core Components)
- [ ] Define a Color Palette:
- [ ] Primary Brand Color: User-specified, used strategically.
- [ ] Neutrals: A scale of grays (5-7 steps) for text, backgrounds, borders.
- [ ] Semantic Colors: Define specific colors for Success (green), Error/Destructive (red), Warning (yellow/amber), Informational (blue).
- [ ] Dark Mode Palette: Create a corresponding accessible dark mode palette.
- [ ] Accessibility Check: Ensure all color combinations meet WCAG AA contrast ratios.
- [ ] Establish a Typographic Scale:
- [ ] Primary Font Family: Choose a clean, legible sans-serif font (e.g., Inter, Manrope, system-ui).
- [ ] Modular Scale: Define distinct sizes for H1, H2, H3, H4, Body Large, Body Medium (Default), Body Small/Caption. (e.g., H1: 32px, Body: 14px/16px).
- [ ] Font Weights: Utilize a limited set of weights (e.g., Regular, Medium, SemiBold, Bold).
- [ ] Line Height: Ensure generous line height for readability (e.g., 1.5-1.7 for body text).
- [ ] Define Spacing Units:
- [ ] Base Unit: Establish a base unit (e.g., 8px).
- [ ] Spacing Scale: Use multiples of the base unit for all padding, margins, and layout spacing (e.g., 4px, 8px, 12px, 16px, 24px, 32px).
- [ ] Define Border Radii:
- [ ] Consistent Values: Use a small set of consistent border radii (e.g., Small: 4-6px for inputs/buttons; Medium: 8-12px for cards/modals).
- [ ] Develop Core UI Components (with consistent states: default, hover, active, focus, disabled):
- [ ] Buttons (primary, secondary, tertiary/ghost, destructive, link-style; with icon options)
- [ ] Input Fields (text, textarea, select, date picker; with clear labels, placeholders, helper text, error messages)
- [ ] Checkboxes & Radio Buttons
- [ ] Toggles/Switches
- [ ] Cards (for content blocks, multimedia items, dashboard widgets)
- [ ] Tables (for data display; with clear headers, rows, cells; support for sorting, filtering)
- [ ] Modals/Dialogs (for confirmations, forms, detailed views)
- [ ] Navigation Elements (Sidebar, Tabs)
- [ ] Badges/Tags (for status indicators, categorization)
- [ ] Tooltips (for contextual help)
- [ ] Progress Indicators (Spinners, Progress Bars)
- [ ] Icons (use a single, modern, clean icon set; SVG preferred)
- [ ] Avatars
III. Layout, Visual Hierarchy & Structure
- [ ] Responsive Grid System: Design based on a responsive grid (e.g., 12-column) for consistent layout across devices.
- [ ] Strategic White Space: Use ample negative space to improve clarity, reduce cognitive load, and create visual balance.
- [ ] Clear Visual Hierarchy: Guide the user's eye using typography (size, weight, color), spacing, and element positioning.
- [ ] Consistent Alignment: Maintain consistent alignment of elements.
- [ ] Main Dashboard Layout:
- [ ] Persistent Left Sidebar: For primary navigation between modules.
- [ ] Content Area: Main space for module-specific interfaces.
- [ ] (Optional) Top Bar: For global search, user profile, notifications.
- [ ] Mobile-First Considerations: Ensure the design adapts gracefully to smaller screens.
IV. Interaction Design & Animations
- [ ] Purposeful Micro-interactions: Use subtle animations and visual feedback for user actions (hovers, clicks, form submissions, status changes).
- [ ] Feedback should be immediate and clear.
- [ ] Animations should be quick (150-300ms) and use appropriate easing (e.g., ease-in-out).
- [ ] Loading States: Implement clear loading indicators (skeleton screens for page loads, spinners for in-component actions).
- [ ] Transitions: Use smooth transitions for state changes, modal appearances, and section expansions.
- [ ] Avoid Distraction: Animations should enhance usability, not overwhelm or slow down the user.
- [ ] Keyboard Navigation: Ensure all interactive elements are keyboard accessible and focus states are clear.
V. Specific Module Design Tactics
A. Multimedia Moderation Module
- [ ] Clear Media Display: Prominent image/video previews (grid or list view).
- [ ] Obvious Moderation Actions: Clearly labeled buttons (Approve, Reject, Flag, etc.) with distinct styling (e.g., primary/secondary, color-coding). Use icons for quick recognition.
- [ ] Visible Status Indicators: Use color-coded Badges for content status (Pending, Approved, Rejected).
- [ ] Contextual Information: Display relevant metadata (uploader, timestamp, flags) alongside media.
- [ ] Workflow Efficiency:
- [ ] Bulk Actions: Allow selection and moderation of multiple items.
- [ ] Keyboard Shortcuts: For common moderation actions.
- [ ] Minimize Fatigue: Clean, uncluttered interface; consider dark mode option.
B. Data Tables Module (Contacts, Admin Settings)
- [ ] Readability & Scannability:
- [ ] Smart Alignment: Left-align text, right-align numbers.
- [ ] Clear Headers: Bold column headers.
- [ ] Zebra Striping (Optional): For dense tables.
- [ ] Legible Typography: Simple, clean sans-serif fonts.
- [ ] Adequate Row Height & Spacing.
- [ ] Interactive Controls:
- [ ] Column Sorting: Clickable headers with sort indicators.
- [ ] Intuitive Filtering: Accessible filter controls (dropdowns, text inputs) above the table.
- [ ] Global Table Search.
- [ ] Large Datasets:
- [ ] Pagination (preferred for admin tables) or virtual/infinite scroll.
- [ ] Sticky Headers / Frozen Columns: If applicable.
- [ ] Row Interactions:
- [ ] Expandable Rows: For detailed information.
- [ ] Inline Editing: For quick modifications.
- [ ] Bulk Actions: Checkboxes and contextual toolbar.
- [ ] Action Icons/Buttons per Row: (Edit, Delete, View Details) clearly distinguishable.
C. Configuration Panels Module (Microsite, Admin Settings)
- [ ] Clarity & Simplicity: Clear, unambiguous labels for all settings. Concise helper text or tooltips for descriptions. Avoid jargon.
- [ ] Logical Grouping: Group related settings into sections or tabs.
- [ ] Progressive Disclosure: Hide advanced or less-used settings by default (e.g., behind "Advanced Settings" toggle, accordions).
- [ ] Appropriate Input Types: Use correct form controls (text fields, checkboxes, toggles, selects, sliders) for each setting.
- [ ] Visual Feedback: Immediate confirmation of changes saved (e.g., toast notifications, inline messages). Clear error messages for invalid inputs.
- [ ] Sensible Defaults: Provide default values for all settings.
- [ ] Reset Option: Easy way to "Reset to Defaults" for sections or entire configuration.
- [ ] Microsite Preview (If Applicable): Show a live or near-live preview of microsite changes.
VI. CSS & Styling Architecture
- [ ] Choose a Scalable CSS Methodology:
- [ ] Utility-First (Recommended for LLM): e.g., Tailwind CSS. Define design tokens in config, apply via utility classes.
- [ ] BEM with Sass: If not utility-first, use structured BEM naming with Sass variables for tokens.
- [ ] CSS-in-JS (Scoped Styles): e.g., Stripe's approach for Elements.
- [ ] Integrate Design Tokens: Ensure colors, fonts, spacing, radii tokens are directly usable in the chosen CSS architecture.
- [ ] Maintainability & Readability: Code should be well-organized and easy to understand.
- [ ] Performance: Optimize CSS delivery; avoid unnecessary bloat.
VII. General Best Practices
- [ ] Iterative Design & Testing: Continuously test with users and iterate on designs.
- [ ] Clear Information Architecture: Organize content and navigation logically.
- [ ] Responsive Design: Ensure the dashboard is fully functional and looks great on all device sizes (desktop, tablet, mobile).
- [ ] Documentation: Maintain clear documentation for the design system and components.
Interaction Patterns & UX Testing Guide
Objective: Verify the interactive experience works as expected Focus: User flows, interactive states, micro-interactions, perceived performance Standard: World-class UX (Stripe, Airbnb, Linear quality)
---
Interactive States Testing
Every interactive element should have clearly defined visual states. Test each state systematically.
The 5 Core Interactive States
1. Default (Resting State)
- How element appears before interaction
- Clear affordance (looks clickable/interactive)
- Visually distinct from non-interactive elements
2. Hover (Mouse Over)
- Provides immediate feedback that element is interactive
- Subtle change (color shift, underline, scale, shadow)
- Smooth transition (150-300ms)
Testing procedure:
# Using Playwright MCP
mcp__playwright__browser_hover(selector: ".button-class")
# Verify visual change in screenshotCommon issues:
- No hover state (looks unresponsive)
- Hover change too subtle (users don't notice)
- Hover transition too fast or slow
3. Active/Pressed (Clicking)
- Visual feedback during click/tap
- Indicates button is responding to input
- Slightly darker or inset appearance
Testing procedure:
# Click and hold to see active state
# Or use DevTools to force :active stateCommon issues:
- No active state (feels unresponsive)
- Same as hover state (no distinction)
4. Focus (Keyboard Navigation)
- Critical for accessibility
- Visible outline or highlight when element receives focus
- Must meet WCAG 3:1 contrast requirement
Testing procedure:
# Tab through page to focus elements
# Verify visible focus indicator on all interactive elementsCommon issues:
outline: nonewith no alternative (accessibility violation)- Focus indicator too subtle (<3:1 contrast)
- Focus state missing on custom components
How to fix:
/* ❌ Bad: Removes focus with no alternative */
button:focus {
outline: none;
}
/* ✅ Good: Custom focus with clear contrast */
button:focus-visible {
outline: 2px solid var(--color-primary-600);
outline-offset: 2px;
}
/* ✅ Good: Visible focus with box-shadow */
button:focus-visible {
box-shadow: 0 0 0 3px rgba(74, 144, 226, 0.4);
}5. Disabled (Non-Interactive)
- Visually muted (lower opacity, grayed out)
- Cursor changes to
not-allowedordefault - No hover or active states
- Still keyboard focusable (but not actionable)
Testing procedure:
# Try clicking disabled elements
# Verify they don't respond
# Tab to them - should skip or show disabled stateCommon issues:
- Disabled elements still clickable
- Disabled state not visually distinct
- Disabled text has poor contrast (<3:1 violates WCAG AA)
---
Form Interaction Patterns
Input Field States
Test each state for all input types (text, email, select, textarea, etc.):
1. Empty (default)
- Placeholder text visible (light gray)
- Cursor changes to text cursor on hover
- Clicking focuses input
2. Focus
- Clear focus indicator (border color change or outline)
- Placeholder remains or disappears
- Cursor blinking
3. Filled
- User input visible
- Placeholder hidden
- Normal appearance
4. Error
- Red border or background tint
- Error message displayed below
- Icon indicating error (optional)
- Clear guidance on how to fix
5. Success/Valid
- Green border or checkmark (optional)
- Confirmation of valid input
- Smooth transition from error state
6. Disabled
- Grayed out appearance
- Not focusable
- Cursor shows
not-allowed
Form Validation Testing
Test validation timing:
1. On blur (recommended):
- Validate when user leaves field
- Don't show errors while typing (annoying)
- Show success/valid state immediately
2. On submit:
- Validate all fields when form submitted
- Scroll to first error
- Focus first error field
Testing procedure:
# 1. Try submitting empty required fields
# 2. Enter invalid data (wrong email format, etc.)
# 3. Verify clear error messages
# 4. Check error messages are associated (aria-describedby)
# 5. Fix errors and verify they clear
# 6. Submit valid form and check success stateCommon issues:
- Validation too aggressive (errors while typing)
- Vague error messages ("Invalid input")
- Errors not associated with inputs (accessibility issue)
- No success confirmation after submit
- Error messages don't clear when fixed
Example: Good form validation
<form>
<div class="form-group">
<label for="email">Email</label>
<input
type="email"
id="email"
aria-invalid="true"
aria-describedby="email-error"
class="error"
>
<span id="email-error" class="error-message" role="alert">
Please enter a valid email address (e.g., you@example.com)
</span>
</div>
</form>---
Button Interaction Patterns
Primary Actions
Testing checklist:
- [ ] Button stands out visually (size, color, weight)
- [ ] Hover state provides feedback
- [ ] Active/pressed state visible
- [ ] Focus state clear for keyboard users
- [ ] Loading state during async actions
- [ ] Disabled state when action unavailable
- [ ] Success state after completion (checkmark, color change)
Loading States
When button triggers async action (API call, navigation):
1. Immediate feedback:
- Button disabled immediately on click
- Text changes ("Submit" → "Submitting...")
- Spinner appears
- User knows action is processing
2. During loading:
- Button remains disabled
- Spinner animation continues
- User can't click again (prevent double-submit)
3. After completion:
- Success state briefly (checkmark, "Saved!")
- Then return to default or navigate away
Testing procedure:
# Click button that triggers API call
# Verify immediate disabled state
# Check for spinner or loading text
# Wait for completion
# Verify success feedbackCommon issues:
- No immediate feedback (appears unresponsive)
- User can click multiple times (double-submit)
- No confirmation after success
- Button stays disabled after error
Example: Good loading button
<button
class="btn-primary"
:disabled="isLoading"
@click="handleSubmit"
>
<span v-if="!isLoading">Submit</span>
<span v-if="isLoading">
<spinner /> Submitting...
</span>
</button>---
Destructive Actions
Confirmation Patterns
All destructive actions should have confirmation:
Destructive actions include:
- Delete (item, account, data)
- Cancel (unsaved changes)
- Leave page (with unsaved changes)
- Irreversible operations
Confirmation levels:
1. Inline confirmation (for recoverable actions):
- "Are you sure?" with Yes/No buttons
- Quick, doesn't leave context
2. Modal confirmation (for important deletions):
- Separate modal dialog
- Clear explanation of what will be deleted
- Require typing confirmation ("Type DELETE to confirm")
- Cancel button prominent
3. Undo action (best UX):
- Action happens immediately
- Toast message: "Item deleted. Undo?"
- Allow undo within 5-10 seconds
- Less friction, still safe
Testing procedure:
# Try deleting an item
# Verify confirmation dialog appears
# Test Cancel button (nothing happens)
# Test Confirm button (item deleted)
# Check for undo option (if applicable)Common issues:
- Delete button with no confirmation (dangerous!)
- Confirmation not clear about what's being deleted
- Cancel button styled the same as confirm (confusing)
- No way to undo accidental deletions
Example: Good destructive action
<!-- Modal confirmation for deletion -->
<div role="dialog" aria-labelledby="delete-title">
<h2 id="delete-title">Delete project?</h2>
<p>
Are you sure you want to delete "<strong>My Project</strong>"?
This action cannot be undone.
</p>
<div class="actions">
<button class="btn-secondary" @click="cancel">Cancel</button>
<button class="btn-destructive" @click="confirmDelete">
Delete project
</button>
</div>
</div>---
Navigation & Flow Testing
User Flow Testing
Test primary user flows based on PR notes or typical usage:
1. Map out the flow:
- What's the user trying to accomplish?
- What are the steps?
- What's the expected outcome?
2. Execute the flow:
- Navigate through each step
- Verify each step works as expected
- Check for friction points
3. Check edge cases:
- What if user goes back?
- What if they refresh mid-flow?
- What if they skip optional steps?
Example flow: E-commerce checkout
1. Add item to cart → Cart updates (badge count increases)
2. Go to cart → See cart summary
3. Click checkout → Navigate to checkout page
4. Enter shipping info → Form validates on blur
5. Enter payment info → Secure form, masked data
6. Review order → Can edit before submitting
7. Submit order → Loading state, then confirmation
8. See confirmation → Order number, email sentTesting checklist for each step:
- [ ] Navigation works (buttons, links functional)
- [ ] Data persists between steps
- [ ] Back button behavior makes sense
- [ ] Progress indicator (if multi-step)
- [ ] Each step has clear next action
- [ ] Error states handled gracefully
---
Micro-Interactions
Purposeful Animations
Good micro-interactions provide:
- Feedback: Confirming user action
- Feedforward: Showing what will happen
- Relationships: Showing connections between elements
- Continuity: Smooth transitions between states
Animation Best Practices
Timing:
- Fast: 100-200ms for simple transitions (hover, focus)
- Medium: 200-400ms for moderate changes (expand/collapse)
- Slow: 400-600ms for major state changes (page transitions)
Easing:
- Ease-in-out: General purpose (accelerate then decelerate)
- Ease-out: Elements entering (decelerates)
- Ease-in: Elements exiting (accelerates)
Testing procedure:
# Interact with all animated elements
# Verify animations feel natural (not too fast/slow)
# Check for jank or stuttering
# Test on slower devices if possibleCommon animation issues:
- Too fast (jarring, hard to follow)
- Too slow (feels sluggish, annoying)
- Animating expensive properties (width, height instead of transform)
- No animation (feels abrupt)
- Too much animation (overwhelming, distracting)
Example: Good micro-interactions
/* Button hover - quick feedback */
.button {
transition: background-color 150ms ease-in-out;
}
/* Accordion expand - moderate timing */
.accordion-content {
transition: height 300ms ease-out;
}
/* Modal appearance - smooth entry */
.modal {
animation: fadeIn 200ms ease-out;
}
@keyframes fadeIn {
from {
opacity: 0;
transform: scale(0.95);
}
to {
opacity: 1;
transform: scale(1);
}
}---
Perceived Performance
Making Interfaces Feel Fast
Even if actual performance is slow, perceived performance can be improved:
1. Optimistic UI updates:
- Update UI immediately, assuming success
- Revert if operation fails
- Example: Like button turns blue instantly, then syncs with server
2. Skeleton screens:
- Show layout placeholders while loading
- Better than blank screen or spinner
- Feels faster because something is visible
3. Progressive loading:
- Load critical content first
- Load non-critical content after
- Example: Load text immediately, images lazy-load
4. Instant feedback:
- Show loading state within 100ms of user action
- Don't wait for server response to show something happened
Testing checklist:
- [ ] Actions feel snappy (<100ms feedback)
- [ ] Loading states prevent user confusion
- [ ] Skeleton screens used for slow loads
- [ ] Optimistic updates for common actions
- [ ] No long waits without indication
---
Modal & Dialog Patterns
Modal Interaction Testing
Opening:
- [ ] Modal appears smoothly (fade in, scale up)
- [ ] Background dimmed/blurred (focus on modal)
- [ ] Focus moves to modal (keyboard trap)
- [ ] Body scroll disabled (prevent scrolling behind modal)
Inside modal:
- [ ] Tab navigation stays within modal
- [ ] Escape key closes modal
- [ ] Clear close button (X in top-right)
- [ ] Can't click outside modal accidentally
Closing:
- [ ] Multiple ways to close (X button, Cancel, Escape, click overlay)
- [ ] Focus returns to trigger element
- [ ] Modal exits smoothly (fade out)
- [ ] Body scroll re-enabled
Common modal issues:
- Focus not trapped (can Tab to elements behind modal)
- No Escape key handler
- Clicking overlay closes modal accidentally (for important confirmations)
- Focus lost after closing (returns to body instead of trigger)
- Background scrolls while modal open
---
Keyboard Navigation Testing
Complete Keyboard Test
Test procedure: 1. Disconnect mouse (or don't use it) 2. Tab through entire page from top to bottom 3. Verify each interactive element:
- Receives visible focus
- Can be activated (Enter or Space)
- Logical tab order (reading order)
4. Test modals:
- Open with Enter
- Navigate within modal
- Close with Escape
5. Test dropdowns and menus:
- Open with Enter
- Navigate with arrow keys
- Close with Escape
6. Test forms:
- Tab between fields
- Select options with arrow keys
- Submit with Enter
Common keyboard issues:
- Tab order illogical (jumps around page)
- Focus invisible (outline removed, no alternative)
- Can't activate custom components (divs instead of buttons)
- Keyboard trap (can't Tab out of component)
- No way to close modals with keyboard
---
Dropdown & Select Patterns
Native Select
- [ ] Opens on click
- [ ] Keyboard navigable (arrow keys)
- [ ] Searchable by typing
- [ ] Closes on selection or Escape
Custom Dropdown
- [ ] Keyboard accessible (Enter to open, arrows to navigate)
- [ ] Visible focus on options
- [ ] Closes on Escape or outside click
- [ ] ARIA attributes (aria-expanded, aria-haspopup, aria-activedescendant)
---
Quick Interaction Testing Checklist
For every interactive element:
- [ ] Default state looks interactive (affordance)
- [ ] Hover state provides feedback
- [ ] Active/pressed state visible
- [ ] Focus state clear (outline or highlight)
- [ ] Disabled state visually distinct
- [ ] Keyboard accessible (Enter/Space activates)
For forms:
- [ ] Validation on blur (not while typing)
- [ ] Clear error messages with guidance
- [ ] Errors associated with inputs (aria-describedby)
- [ ] Success confirmation after submit
- [ ] Loading state during submission
For destructive actions:
- [ ] Confirmation required
- [ ] Clear explanation of consequences
- [ ] Cancel option prominent
- [ ] Undo available (if possible)
For modals:
- [ ] Focus trapped within modal
- [ ] Escape key closes modal
- [ ] Background dimmed
- [ ] Focus returns to trigger after closing
For animations:
- [ ] Timing feels natural (150-300ms for simple)
- [ ] Easing appropriate (ease-in-out general)
- [ ] No jank or stuttering
- [ ] Not overwhelming or distracting
---
Triage Priorities
[Blocker]:
- Core user flow broken or inaccessible
- Destructive action with no confirmation
- Keyboard trap (can't escape)
[High]:
- Missing focus states (keyboard nav broken)
- Poor UX (confusing flow, no feedback)
- Missing loading states (appears frozen)
[Medium]:
- Minor interaction issues
- Missing hover states
- Suboptimal timing on animations
[Nitpick]:
- Animation easing preferences
- Minor timing adjustments
- Aesthetic micro-interaction details
---
Resources:
- Inclusive Components: https://inclusive-components.design/
- Material Design - Motion: https://material.io/design/motion/
- Laws of UX: https://lawsofux.com/