How to Ensure Accessibility for Reduced Motion Users with the Taste Skill

The Taste Skill enforces accessibility by requiring all animations with a MOTION_INTENSITY greater than 3 to detect and respect the user's prefers-reduced-motion setting using the useReducedMotion() hook from motion/react or CSS media query fallbacks.

The Leonxlnx/taste-skill repository provides a disciplined motion system that ensures high-quality animations remain fully accessible to users with vestibular disorders or motion sensitivity. By implementing intensity-based thresholds and leveraging the Motion library's detection APIs, developers can ship rich interfaces that automatically adapt to user preferences without manual configuration.

Understanding the Motion Intensity Framework

The Taste Skill defines a strict motion scale from 1 to 10, where every animation must declare its MOTION_INTENSITY level. According to skills/taste-skill/SKILL.md at lines 526-529, any implementation with an intensity greater than 3 must honor the user's prefers-reduced-motion preference. This threshold separates subtle micro-interactions from prominent motion that could trigger discomfort.

This requirement is not merely suggested—it is treated as a non-negotiable design standard. When planning animations, you must first categorize the visual impact and prepare appropriate fallbacks for any motion above the intensity threshold of 3.

Detecting Reduced Motion with useReducedMotion()

For React components, the Taste Skill mandates importing from the Motion library (motion/react), the modern alias of Framer Motion. To programmatically detect user preferences, utilize the useReducedMotion() hook, which returns true whenever the browser detects an active prefers-reduced-motion: reduce media query.

As documented in skills/taste-skill/SKILL.md at lines 372-434, this hook allows you to conditionally disable spring physics, instant transitions, or complex stagger effects. The implementation pattern requires checking the boolean before defining transition properties.

import { motion, useReducedMotion } from "motion/react";

/* 1️⃣  Simple component that respects reduced motion */
export function Card({ children }: { children: React.ReactNode }) {
  const shouldReduce = useReducedMotion();      // ← detects user preference

  // Choose variant based on preference
  const variants = {
    visible: {
      opacity: 1,
      y: 0,
      transition: shouldReduce
        ? { duration: 0 }               // instantly appear when reduced motion
        : { type: "spring", stiffness: 120, damping: 20 },
    },
    hidden: { opacity: 0, y: 20 },
  };

  return (
    <motion.div
      initial="hidden"
      animate="visible"
      variants={variants}
    >
      {children}
    </motion.div>
  );
}

CSS Media Query Fallbacks

For animations defined in stylesheets rather than React components, the Taste Skill requires explicit media query guards. Any CSS keyframe animation must be wrapped in @media (prefers-reduced-motion: no-preference) and include a fallback that sets animation: none when the reduced motion preference is active.

This pattern is specified in skills/taste-skill/SKILL.md at lines 528-531 as the mandatory CSS implementation strategy.

/* 2️⃣  CSS animation guarded by a media query */
@media (prefers-reduced-motion: no-preference) {
  .pulse {
    animation: pulse 2s infinite ease-in-out;
  }
}
@media (prefers-reduced-motion: reduce) {
  .pulse {
    animation: none;                     /* static fallback */
  }
}

Handling Perpetual Animations

Continuous micro-interactions—such as floating icons, spinning loaders, or pulsing indicators—require complete elimination rather than mere reduction when accessibility preferences are detected. The recommended pattern uses conditional rendering to swap animated elements for static equivalents.

The following example from the skill documentation demonstrates skipping infinite loops entirely:

import { motion, useReducedMotion } from "motion/react";

/* 3️⃣  Conditional rendering of a perpetual micro‑interaction */
export function FloatingIcon() {
  const reduce = useReducedMotion();

  // Skip the infinite floating animation when reduced motion is on
  return reduce ? (
    <svg className="static-icon" … />
  ) : (
    <motion.svg
      className="floating-icon"
      animate={{ y: [-5, 5] }}
      transition={{ repeat: Infinity, duration: 2, ease: "easeInOut" }}
    />
  );
}

Enforcement and Design Standards

Compliance with reduced motion accessibility is enforced through the skill's mandatory checklist. According to CHANGELOG.md at lines 74-75, the rule explicitly states: "Any motion above MOTION_INTENSITY > 3 MUST honor prefers-reduced-motion". Violations of this standard are treated as blocking issues during code review.

All implementations must reference the authoritative guidelines in skills/taste-skill/SKILL.md, which details the approved motion/react imports at line 132 and the complete useReducedMotion integration patterns at lines 372-434.

Summary

  • Intensity threshold: Any animation with MOTION_INTENSITY greater than 3 must detect and respond to prefers-reduced-motion settings.
  • React detection: Import useReducedMotion from motion/react (the modern Framer Motion alias) to conditionally modify or disable animations.
  • CSS protection: Wrap keyframe animations in @media (prefers-reduced-motion: no-preference) blocks with explicit reduce fallbacks that disable motion.
  • Eliminate perpetual motion: Remove infinite animations entirely when reduced motion is preferred, rather than slowing them down.
  • Mandatory compliance: The Taste Skill enforces these rules through design checklists and change log requirements, making accessibility a non-negotiable deliverable.

Frequently Asked Questions

How does the Taste Skill define motion intensity levels?

The skill categorizes animations on a scale of 1 to 10, where values 1-3 represent subtle transitions and values above 3 indicate prominent, attention-grabbing motion. As defined in skills/taste-skill/SKILL.md at lines 526-529, any implementation exceeding intensity level 3 falls under strict accessibility requirements and must detect the prefers-reduced-motion media query before rendering animations.

Can I use the standard Framer Motion package instead of motion/react?

While Framer Motion provides the underlying functionality, the Taste Skill specifically requires importing from motion/react as documented at line 132 of skills/taste-skill/SKILL.md. This modern alias ensures consistency across the codebase and guarantees access to the latest accessibility APIs, including the useReducedMotion hook.

What happens if I don't implement reduced motion detection for high-intensity animations?

The Taste Skill treats reduced motion compliance as a blocking requirement. As noted in CHANGELOG.md at lines 74-75, any animation with MOTION_INTENSITY > 3 that fails to honor prefers-reduced-motion violates the skill's non-negotiable standards and will prevent deployment or require immediate remediation during the review process.

Should I slow down animations or disable them entirely for accessibility?

Disable them entirely. For entrance and exit effects, set transition duration to 0 for instant state changes. For continuous micro-interactions like floating icons, completely remove the animation and render a static variant as shown in the FloatingIcon example. The goal is to eliminate vestibular triggers while preserving functional UI elements, not merely to reduce animation speed.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →