All skills
asyrafhussin avatar

/web-design-guidelines

@b73c638

UI/UX best practices and accessibility audit. Use when reviewing UI code, checking accessibility, running accessibility audits, auditing forms, or ensuring web interface best practices. Triggers on "audit accessibility", "check WCAG", "review UI", "check accessibility", "audit design", "review UX", or "check best practices".

Use this Skill: https://skilld.dev/gh/asyrafhussin/agent-skills/web-design-guidelines

This session only. Nothing lands on disk.

rulesmotion-reduced.md

≈1.4k tokens on demand. Your agent reads this file only when SKILL.md points to it.

Respect Prefers-Reduced-Motion

Impact: CRITICAL (WCAG 2.1 Level AAA - Animation from interactions)

Some users experience motion sickness, vestibular disorders, or distraction from animations. The prefers-reduced-motion media query lets users opt out of non-essential motion. Respecting this preference is crucial for accessibility.

Incorrect

// ❌ Bad: No reduced motion consideration
<div className="animate-bounce">
  Bouncing element
</div>

// ❌ Bad: JavaScript animations without check
useEffect(() => {
  animate(element, { x: 100 }, { duration: 1000 })
}, [])

Problems:

  • Animations play regardless of user preference, triggering vestibular disorders
  • No CSS or JavaScript checks for the prefers-reduced-motion media query
  • Continuous animations (bounce, pulse) are especially problematic
  • Users have no way to opt out of motion on the page

Correct

CSS Approach

/* ✅ Good: Base - no animation for reduced motion preference */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

/* Or selectively disable */
.hero-animation {
  animation: float 3s ease-in-out infinite;
}

@media (prefers-reduced-motion: reduce) {
  .hero-animation {
    animation: none;
  }
}

Tailwind CSS

// ✅ Good: Use motion-reduce variant
<div className="
  transition-transform duration-300
  hover:scale-105
  motion-reduce:transition-none
  motion-reduce:hover:transform-none
">
  Hover me
</div>

// ✅ Good: Disable animation for reduced motion
<div className="
  animate-pulse
  motion-reduce:animate-none
">
  Loading...
</div>

// ✅ Good: Simplify rather than remove
<div className="
  transition-all duration-300 ease-out
  motion-reduce:transition-opacity motion-reduce:duration-150
">
  {/* Keeps opacity fade but removes transform */}
</div>

JavaScript Check

// ✅ Good: Hook for checking preference
function usePrefersReducedMotion(): boolean {
  const [prefersReducedMotion, setPrefersReducedMotion] = useState(false)

  useEffect(() => {
    const mediaQuery = window.matchMedia('(prefers-reduced-motion: reduce)')

    setPrefersReducedMotion(mediaQuery.matches)

    const handler = (event: MediaQueryListEvent) => {
      setPrefersReducedMotion(event.matches)
    }

    mediaQuery.addEventListener('change', handler)
    return () => mediaQuery.removeEventListener('change', handler)
  }, [])

  return prefersReducedMotion
}

// Usage
function AnimatedComponent() {
  const prefersReducedMotion = usePrefersReducedMotion()

  return (
    <motion.div
      initial={{ opacity: 0, y: prefersReducedMotion ? 0 : 20 }}
      animate={{ opacity: 1, y: 0 }}
      transition={{ duration: prefersReducedMotion ? 0 : 0.3 }}
    >
      Content
    </motion.div>
  )
}

Framer Motion Integration

// ✅ Good: Framer Motion reduced motion support
import { motion, useReducedMotion } from 'framer-motion'

function Card() {
  const shouldReduceMotion = useReducedMotion()

  return (
    <motion.div
      initial={{ opacity: 0, scale: shouldReduceMotion ? 1 : 0.9 }}
      animate={{ opacity: 1, scale: 1 }}
      transition={{
        duration: shouldReduceMotion ? 0.001 : 0.3,
      }}
      whileHover={shouldReduceMotion ? {} : { scale: 1.05 }}
    >
      Card content
    </motion.div>
  )
}

Animation with Fallback

// ✅ Good: Show static alternative for reduced motion
function LoadingIndicator() {
  const prefersReducedMotion = usePrefersReducedMotion()

  if (prefersReducedMotion) {
    return <span>Loading...</span>  // Text instead of spinner
  }

  return (
    <div className="animate-spin rounded-full h-8 w-8 border-2 border-blue-600 border-t-transparent" />
  )
}

Benefits:

  • Users with vestibular disorders can browse without triggering motion sickness
  • Respects user OS-level preference for reduced motion
  • Reduces CPU and battery usage when animations are disabled
  • WCAG 2.3.3 Animation from Interactions compliance
  • Provides static alternatives that preserve the information conveyed by animation

What to Keep vs Remove

Should Reduce/Remove

  • Parallax effects
  • Hover animations on non-interactive elements
  • Loading spinners (use text)
  • Page transition animations
  • Auto-playing carousels
  • Continuous animations (pulse, bounce)

Can Keep (Essential Motion)

  • Progress indicators
  • Micro-interactions that provide feedback
  • Opacity transitions (usually fine)
  • Focus indicators
  • State change indicators
// ✅ Good: Essential feedback - keep but simplify
<button
  className={cn(
    'transition-colors',  // Color change is usually OK
    'motion-reduce:transition-none',
    'motion-safe:hover:scale-105 motion-safe:active:scale-95'  // Scale only for motion-safe
  )}
>
  Submit
</button>

Testing

// Simulate in DevTools:
// Chrome: Rendering panel > Emulate CSS media feature > prefers-reduced-motion
// Firefox: about:config > ui.prefersReducedMotion (0=no-preference, 1=reduce)

// Or in CSS:
@media (prefers-reduced-motion: no-preference) {
  /* Animations for users who haven't opted out */
}

@media (prefers-reduced-motion: reduce) {
  /* Reduced/no animations */
}

Reference: WCAG 2.3.3 Animation from Interactions

Source: SKILL.md on GitHub

2 warnings16d5 checks · Risk SAFE
  • Gen Agent Trust Hub16d

    The skill provides comprehensive guidelines for accessibility and web design audits. It processes user-provided code files to generate compliance reports, which introduces a minor risk of indirect prompt injection if the audited files contain malicious instructions. No evidence of data exfiltration, obfuscation, or unauthorized command execution was found.

  • Socket16d

    2 alerts: gptAnomaly

  • Snyk16d

    Risk: LOW · No issues

  • Runlayer7mo

    26/27 files flagged

  • ZeroLeaks5mo

    Score: 93/100 · 2 sections analyzed

Signed by skilld at b73c638. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub last month.

Steadyupdated 6 months ago
metadata
{
  "author": "agent-skills",
  "version": "2.1.0"
}

README badge

README badge for asyrafhussin/agent-skills/web-design-guidelines