animation-interaction-validator

Ensures engaging user experience through validation of animations, transitions, micro-interactions, and feedback states, preventing flat/static interfaces that lack polish and engagement. Works with Tanstack Start (React) + shadcn/ui components.

16 stars

Best use case

animation-interaction-validator is best used when you need a repeatable AI agent workflow instead of a one-off prompt.

Ensures engaging user experience through validation of animations, transitions, micro-interactions, and feedback states, preventing flat/static interfaces that lack polish and engagement. Works with Tanstack Start (React) + shadcn/ui components.

Teams using animation-interaction-validator should expect a more consistent output, faster repeated execution, less prompt rewriting.

When to use this skill

  • You want a reusable workflow that can be run more than once with consistent structure.

When not to use this skill

  • You only need a quick one-off answer and do not need a reusable workflow.
  • You cannot install or maintain the underlying files, dependencies, or repository context.

Installation

Claude Code / Cursor / Codex

$curl -o ~/.claude/skills/animation-interaction-validator/SKILL.md --create-dirs "https://raw.githubusercontent.com/diegosouzapw/awesome-omni-skill/main/skills/frontend/animation-interaction-validator/SKILL.md"

Manual Installation

  1. Download SKILL.md from GitHub
  2. Place it in .claude/skills/animation-interaction-validator/SKILL.md inside your project
  3. Restart your AI agent — it will auto-discover the skill

How animation-interaction-validator Compares

Feature / Agentanimation-interaction-validatorStandard Approach
Platform SupportNot specifiedLimited / Varies
Context Awareness High Baseline
Installation ComplexityUnknownN/A

Frequently Asked Questions

What does this skill do?

Ensures engaging user experience through validation of animations, transitions, micro-interactions, and feedback states, preventing flat/static interfaces that lack polish and engagement. Works with Tanstack Start (React) + shadcn/ui components.

Where can I find the source code?

You can find the source code on GitHub using the link provided at the top of the page.

SKILL.md Source

# Animation Interaction Validator SKILL

## Activation Patterns

This SKILL automatically activates when:
- Interactive elements are created (buttons, links, forms, inputs)
- Click, hover, or focus event handlers are added
- Component state changes (loading, success, error)
- Async operations are initiated (API calls, form submissions)
- Navigation or routing transitions occur
- Modal/dialog components are opened/closed
- Lists or data are updated dynamically

## Expertise Provided

### Animation & Interaction Validation
- **Transition Detection**: Ensures smooth state changes with CSS transitions
- **Hover State Validation**: Checks for hover feedback on interactive elements
- **Loading State Validation**: Ensures async actions have visual feedback
- **Micro-interaction Analysis**: Validates small, delightful animations
- **Focus State Validation**: Ensures keyboard navigation has visual feedback
- **Animation Performance**: Checks for performant animation patterns

### Specific Checks Performed

#### ❌ Critical Issues (Missing Feedback)
```tsx
// These patterns trigger alerts:

// No hover state
<Button onClick={submit}>Submit</Button>

// No loading state during async action
<Button onClick={async () => await submitForm()}>Save</Button>

// Jarring state change (no transition)
{showContent && <div>Content</div>}

// No focus state
<a href="/page" className="text-blue-500">Link</a>

// Form without feedback
<form onSubmit={handleSubmit}>
  <Input value={value} onChange={setValue} />
  <button type="submit">Submit</button>
</form>
```

#### ✅ Correct Interactive Patterns
```tsx
import { Button } from "@/components/ui/button"
import { Input } from "@/components/ui/input"
import { Send } from "lucide-react"
import { cn } from "@/lib/utils"

// These patterns are validated as correct:

// Hover state with smooth transition
<Button
  className="transition-all duration-300 hover:scale-105 hover:shadow-xl active:scale-95"
  onClick={submit}
>
  Submit
</Button>

// Loading state with visual feedback
<Button
  disabled={isSubmitting}
  className="transition-all duration-200 group"
  onClick={handleSubmit}
>
  <span className="flex items-center gap-2">
    {!isSubmitting && (
      <Send className="h-4 w-4 transition-transform duration-300 group-hover:translate-x-1" />
    )}
    {isSubmitting ? 'Submitting...' : 'Submit'}
  </span>
</Button>

// Smooth state transition (using framer-motion or CSS)
<div
  className={cn(
    "transition-all duration-300 ease-out",
    showContent ? "opacity-100 translate-y-0" : "opacity-0 translate-y-4"
  )}
>
  {showContent && <div>Content</div>}
</div>

// Focus state with ring
<a
  href="/page"
  className="text-blue-500 transition-colors duration-200 hover:text-blue-700 focus:outline-none focus-visible:ring-2 focus-visible:ring-blue-500 focus-visible:ring-offset-2"
>
  Link
</a>

<!-- Form with success/error feedback -->
<form onSubmit={(e) => { e.preventDefault(); handleSubmit" className="space-y-4">
  <Input
    value="value"
    error={errors.value"
    className="transition-all duration-200"
  />

  <Button
    type="submit"
    loading={isSubmitting"
    disabled={isSubmitting"
    className="transition-all duration-300 hover:scale-105"
  >
    Submit
  </Button>

  <!-- Success message with animation -->
  <Transition name="fade">
    <Alert
      if="showSuccess"
      color="green"
      icon="i-heroicons-check-circle"
      title="Success!"
      className="animate-in slide-in-from-top"
    />
  </Transition>
</form>
```

## Integration Points

### Complementary to Existing Components
- **frontend-design-specialist agent**: Provides design direction, SKILL validates implementation
- **component-aesthetic-checker**: Validates component customization, SKILL validates interactions
- **shadcn-ui-design-validator**: Catches generic patterns, SKILL ensures engagement
- **accessibility-guardian agent**: Validates a11y, SKILL validates visual feedback

### Escalation Triggers
- Complex animation sequences → `frontend-design-specialist` agent
- Component interaction patterns → `tanstack-ui-architect` agent
- Performance concerns → `edge-performance-oracle` agent
- Accessibility issues → `accessibility-guardian` agent

## Validation Rules

### P1 - Critical (Missing User Feedback)
- **No Hover States**: Buttons/links without hover effects
- **No Loading States**: Async actions without loading indicators
- **Jarring State Changes**: Content appearing/disappearing without transitions
- **No Focus States**: Interactive elements without keyboard focus indicators
- **Silent Errors**: Form errors without visual feedback

### P2 - Important (Enhanced Engagement)
- **No Micro-interactions**: Icons/elements without subtle animations
- **Static Navigation**: Page transitions without animations
- **Abrupt Modals**: Dialogs opening without enter/exit transitions
- **Instant Updates**: List changes without transition animations
- **No Disabled States**: Buttons during processing without visual change

### P3 - Polish (Delightful UX)
- **Limited Animation Variety**: Using only scale/opacity (no rotate, translate)
- **Generic Durations**: Not tuning animation speed for context
- **No Stagger**: List items appearing simultaneously (no stagger effect)
- **Missing Success States**: Completed actions without celebration animation
- **No Hover Anticipation**: No visual hint before interaction is possible

## Remediation Examples

### Fixing Missing Hover States
```tsx
<!-- ❌ Critical: No hover feedback -->
  <Button onClick="handleClick">
    Click me
  </Button>

<!-- ✅ Correct: Multi-dimensional hover effects -->
  <Button
    className="
      transition-all duration-300 ease-out
      hover:scale-105 hover:shadow-xl hover:-rotate-1
      active:scale-95 active:rotate-0
      focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-primary-500
    "
    onClick="handleClick"
  >
    <span className="inline-flex items-center gap-2">
      Click me
      <Icon
        name="i-heroicons-arrow-right"
        className="transition-transform duration-300 group-hover:translate-x-1"
      />
    </span>
  </Button>
```

### Fixing Missing Loading States
```tsx
<!-- ❌ Critical: No loading feedback during async action -->
const submitForm = async () => {
  await api.submit(formData);
};

  <Button onClick="submitForm">
    Submit
  </Button>

<!-- ✅ Correct: Complete loading state with animations -->
const isSubmitting = ref(false);
const showSuccess = ref(false);

const submitForm = async () => {
  isSubmitting.value = true;
  try {
    await api.submit(formData);
    showSuccess.value = true;
    setTimeout(() => showSuccess.value = false, 3000);
  } catch (error) {
    // Error handling
  } finally {
    isSubmitting.value = false;
  }
};

  <div className="space-y-4">
    <Button
      loading={isSubmitting"
      disabled={isSubmitting"
      className="
        transition-all duration-300
        hover:scale-105 hover:shadow-xl
        disabled:opacity-50 disabled:cursor-not-allowed
      "
      onClick="submitForm"
    >
      <span className="flex items-center gap-2">
        <Icon
          if="!isSubmitting"
          name="i-heroicons-paper-airplane"
          className="transition-all duration-300 group-hover:translate-x-1 group-hover:-translate-y-1"
        />
        { isSubmitting ? 'Submitting...' : 'Submit'}
      </span>
    </Button>

    <!-- Success feedback with animation -->
    <Transition
      enter-active-className="transition-all duration-500 ease-out"
      enter-from-className="opacity-0 scale-50"
      enter-to-className="opacity-100 scale-100"
      leave-active-className="transition-all duration-300 ease-in"
      leave-from-className="opacity-100 scale-100"
      leave-to-className="opacity-0 scale-50"
    >
      <Alert
        if="showSuccess"
        color="green"
        icon="i-heroicons-check-circle"
        title="Success!"
        description="Your form has been submitted."
      />
    </Transition>
  </div>
```

### Fixing Jarring State Changes
```tsx
<!-- ❌ Critical: Content appears/disappears abruptly -->
  <div>
    <Button onClick="showContent = !showContent">
      Toggle
    </Button>

    <div if="showContent">
      <p>This content appears instantly (jarring)</p>
    </div>
  </div>

<!-- ✅ Correct: Smooth transitions -->
  <div className="space-y-4">
    <Button
      className="transition-all duration-300 hover:scale-105"
      onClick="showContent = !showContent"
    >
      { showContent ? 'Hide' : 'Show'} Content
    </Button>

    <Transition
      enter-active-className="transition-all duration-300 ease-out"
      enter-from-className="opacity-0 translate-y-4 scale-95"
      enter-to-className="opacity-100 translate-y-0 scale-100"
      leave-active-className="transition-all duration-200 ease-in"
      leave-from-className="opacity-100 translate-y-0 scale-100"
      leave-to-className="opacity-0 translate-y-4 scale-95"
    >
      <div if="showContent" className="p-6 bg-gray-50 dark:bg-gray-800 rounded-lg">
        <p>This content transitions smoothly</p>
      </div>
    </Transition>
  </div>
```

### Fixing Missing Focus States
```tsx
<!-- ❌ Critical: No visible focus state -->
  <nav>
    <a href="/" className="text-gray-700">Home</a>
    <a href="/about" className="text-gray-700">About</a>
    <a href="/contact" className="text-gray-700">Contact</a>
  </nav>

<!-- ✅ Correct: Clear focus states for keyboard navigation -->
  <nav className="flex gap-4">
    <a
      href="/"
      className="
        text-gray-700 dark:text-gray-300
        transition-all duration-200
        hover:text-primary-600 hover:translate-y-[-2px]
        focus:outline-none
        focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2
        rounded px-3 py-2
      "
    >
      Home
    </a>
    <a
      href="/about"
      className="
        text-gray-700 dark:text-gray-300
        transition-all duration-200
        hover:text-primary-600 hover:translate-y-[-2px]
        focus:outline-none
        focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2
        rounded px-3 py-2
      "
    >
      About
    </a>
    <a
      href="/contact"
      className="
        text-gray-700 dark:text-gray-300
        transition-all duration-200
        hover:text-primary-600 hover:translate-y-[-2px]
        focus:outline-none
        focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2
        rounded px-3 py-2
      "
    >
      Contact
    </a>
  </nav>
```

### Adding Micro-interactions
```tsx
<!-- ❌ P2: Static icons without micro-interactions -->
  <Button icon="i-heroicons-heart">
    Like
  </Button>

<!-- ✅ Correct: Animated icon micro-interaction -->
const isLiked = ref(false);
const heartScale = ref(1);

const toggleLike = () => {
  isLiked.value = !isLiked.value;

  // Bounce animation
  heartScale.value = 1.3;
  setTimeout(() => heartScale.value = 1, 200);
};

  <Button
    :color="isLiked ? 'red' : 'gray'"
    className="transition-all duration-300 hover:scale-105"
    onClick="toggleLike"
  >
    <span className="inline-flex items-center gap-2">
      <Icon
        :name="isLiked ? 'i-heroicons-heart-solid' : 'i-heroicons-heart'"
        :style="{ transform: `scale(${heartScale})` }"
        :className="[
          'transition-all duration-200',
          isLiked ? 'text-red-500 animate-pulse' : 'text-gray-500'
        ]"
      />
      { isLiked ? 'Liked' : 'Like'}
    </span>
  </Button>
```

## Animation Best Practices

### Performance-First Animations

✅ **Performant Properties** (GPU-accelerated):
- `transform` (translate, scale, rotate)
- `opacity`
- `filter` (backdrop-blur, etc.)

❌ **Avoid Animating** (causes reflow/repaint):
- `width`, `height`
- `top`, `left`, `right`, `bottom`
- `margin`, `padding`
- `border-width`

```tsx
<!-- ❌ P2: Animating width (causes reflow) -->
<div className="transition-all hover:w-64">Content</div>

<!-- ✅ Correct: Using transform (GPU-accelerated) -->
<div className="transition-transform hover:scale-110">Content</div>
```

### Animation Duration Guidelines

- **Fast** (100-200ms): Hover states, small movements
- **Medium** (300-400ms): State changes, content transitions
- **Slow** (500-800ms): Page transitions, major UI changes
- **Very Slow** (1000ms+): Celebration animations, complex sequences

```tsx
<!-- Context-appropriate durations -->
<Button className="transition-all duration-200 hover:scale-105">
  <!-- Fast hover: 200ms -->
</Button>

<Transition
  enter-active-className="transition-all duration-300"
  leave-active-className="transition-all duration-300"
>
  <!-- Content change: 300ms -->
  <div if="show">Content</div>
</Transition>

<div className="animate-in slide-in-from-bottom duration-500">
  <!-- Page load: 500ms -->
  Main content
</div>
```

### Easing Functions

- `ease-out`: Starting animations (entering content)
- `ease-in`: Ending animations (exiting content)
- `ease-in-out`: Bidirectional animations
- `linear`: Loading spinners, continuous animations

```tsx
<!-- Appropriate easing -->
<Transition
  enter-active-className="transition-all duration-300 ease-out"
  leave-active-className="transition-all duration-200 ease-in"
>
  <div if="show">Content</div>
</Transition>
```

## Advanced Interaction Patterns

### Staggered List Animations
```tsx
const items = ref([1, 2, 3, 4, 5]);

  <TransitionGroup
    name="list"
    tag="div"
    className="space-y-2"
  >
    <div
      map((item, index) in items"
      :key="item"
      :style="{ transitionDelay: `${index * 50}ms` }"
      className="
        transition-all duration-300 ease-out
        hover:scale-105 hover:shadow-lg
      "
    >
      Item { item}
    </div>
  </TransitionGroup>

<style scoped>
.list-enter-active,
.list-leave-active {
  transition: all 0.3s ease;
}

.list-enter-from {
  opacity: 0;
  transform: translateX(-20px);
}

.list-leave-to {
  opacity: 0;
  transform: translateX(20px);
}

.list-move {
  transition: transform 0.3s ease;
}
</style>
```

### Success Celebration Animation
```tsx
const showSuccess = ref(false);

const celebrate = () => {
  showSuccess.value = true;
  // Confetti or celebration animation here
  setTimeout(() => showSuccess.value = false, 3000);
};

  <div>
    <Button
      onClick="celebrate"
      className="transition-all duration-300 hover:scale-110 hover:rotate-3"
    >
      Complete Task
    </Button>

    <Transition
      enter-active-className="transition-all duration-500 ease-out"
      enter-from-className="opacity-0 scale-0 rotate-180"
      enter-to-className="opacity-100 scale-100 rotate-0"
    >
      <div
        if="showSuccess"
        className="fixed inset-0 flex items-center justify-center bg-black/20 backdrop-blur-sm"
      >
        <div className="bg-white dark:bg-gray-800 p-8 rounded-2xl shadow-2xl">
          <Icon
            name="i-heroicons-check-circle"
            className="w-16 h-16 text-green-500 animate-bounce"
          />
          <p className="mt-4 text-xl font-heading">Success!</p>
        </div>
      </div>
    </Transition>
  </div>
```

### Loading Skeleton with Pulse
```tsx
  <div if="loading" className="space-y-4">
    <div className="animate-pulse">
      <div className="h-4 bg-gray-200 dark:bg-gray-700 rounded w-3/4"></div>
      <div className="h-4 bg-gray-200 dark:bg-gray-700 rounded w-1/2 mt-2"></div>
      <div className="h-32 bg-gray-200 dark:bg-gray-700 rounded mt-4"></div>
    </div>
  </div>

  <Transition
    enter-active-className="transition-all duration-500 ease-out"
    enter-from-className="opacity-0 translate-y-4"
    enter-to-className="opacity-100 translate-y-0"
  >
    <div if="!loading">
      <!-- Actual content -->
    </div>
  </Transition>
```

## MCP Server Integration

While this SKILL doesn't directly use MCP servers, it complements MCP-enhanced agents:

- **shadcn/ui MCP**: Validates that suggested animations work with shadcn/ui components
- **Cloudflare MCP**: Ensures animations don't bloat bundle size (performance check)

## Benefits

### Immediate Impact
- **Prevents Flat UI**: Ensures engaging, polished interactions
- **Improves Perceived Performance**: Loading states make waits feel shorter
- **Better Accessibility**: Focus states improve keyboard navigation
- **Professional Polish**: Micro-interactions signal quality

### Long-term Value
- **Higher User Engagement**: Delightful animations encourage interaction
- **Reduced Bounce Rate**: Polished UI keeps users engaged
- **Better Brand Perception**: Professional animations signal quality
- **Consistent UX**: All interactions follow same animation patterns

## Usage Examples

### During Button Creation
```tsx
// Developer adds: <Button onClick="submit">Submit</Button>
// SKILL immediately activates: "⚠️ P1: Button lacks hover state. Add transition utilities: class='transition-all duration-300 hover:scale-105'"
```

### During Async Action
```tsx
// Developer creates: const submitForm = async () => { await api.call(); }
// SKILL immediately activates: "⚠️ P1: Async action without loading state. Add :loading and :disabled props to button."
```

### During State Toggle
```tsx
// Developer adds: <div if="show">Content</div>
// SKILL immediately activates: "⚠️ P1: Content appears abruptly. Wrap with <Transition> for smooth state changes."
```

### Before Deployment
```tsx
// SKILL runs comprehensive check: "✅ Animation validation passed. 45 interactive elements with hover states, 12 async actions with loading feedback, 8 smooth transitions detected."
```

This SKILL ensures every interactive element provides engaging visual feedback, preventing the flat, static appearance that makes interfaces feel unpolished and reduces user engagement.

Related Skills

animation

16
from diegosouzapw/awesome-omni-skill

Expert guidance for creating premium, performant animations in React using Motion (motion.dev). Covers all animation types, best practices, accessibility, and performance optimization.

animation-motion

16
from diegosouzapw/awesome-omni-skill

Create smooth animations and micro-interactions with Framer Motion and CSS. Covers enter/exit animations, gestures, scroll animations, loading states, and performance optimization. Use for polished UIs, interactive elements, and engaging user experiences.

ai-output-validator

16
from diegosouzapw/awesome-omni-skill

AI出力の品質を自動検証するスキル。事実確認、論理性、一貫性、幻覚(ハルシネーション)検出、バイアス分析、安全性チェックを実施し、改善提案を提供。

documentation-structure-validator

16
from diegosouzapw/awesome-omni-skill

Validate documentation structure, check for missing sections, verify markdown syntax, ensure consistency with templates. Use when user mentions docs validation, structure check, README review, documentation quality, or wants to verify documentation completeness.

doc-validator

16
from diegosouzapw/awesome-omni-skill

Validate documentation files for completeness, accuracy, and consistency with the codebase. Use when user mentions "check documentation", "validate docs", "is the README up to date?", requests documentation review, says "docs are wrong" or "fix the docs", or is working on documentation improvements. Covers README files, API docs, CHANGELOG, and any markdown documentation.

yaml-validator

16
from diegosouzapw/awesome-omni-skill

Comprehensive YAML syntax validation, error fixing, and schema validation for various formats (GitHub Actions, Docker Compose, Kubernetes, GitLab CI). Use when Claude needs to: (1) Validate YAML syntax, (2) Check YAML files for errors, (3) Fix common YAML formatting issues, (4) Validate against schemas like GitHub Actions workflows, Docker Compose files, Kubernetes manifests, or GitLab CI pipelines, (5) Debug YAML parsing errors. Triggers on phrases like "check yaml", "validate yaml", "fix yaml errors", "yaml syntax".

terraform-validator

16
from diegosouzapw/awesome-omni-skill

Comprehensive toolkit for validating, linting, testing, and automating Terraform configurations and HCL files. Use this skill when working with Terraform files (.tf, .tfvars), validating infrastructure-as-code, debugging Terraform configurations, performing dry-run testing with terraform plan, or working with custom providers and modules.

k8s-yaml-validator

16
from diegosouzapw/awesome-omni-skill

Comprehensive toolkit for validating, linting, and testing Kubernetes YAML resources. Use this skill when validating Kubernetes manifests, debugging YAML syntax errors, performing dry-run tests on clusters, or working with Custom Resource Definitions (CRDs) that require documentation lookup.

gitlab-ci-validator

16
from diegosouzapw/awesome-omni-skill

Comprehensive toolkit for validating, linting, testing, and securing GitLab CI/CD pipeline configurations. Use this skill when working with GitLab CI/CD pipelines, validating pipeline syntax, debugging configuration issues, or implementing best practices.

citation-link-validator

16
from diegosouzapw/awesome-omni-skill

Validates footnote links in articles to prevent broken 404 URLs. Use when Claude needs to generate content with reference citations (research reports, technical documentation, academic articles). Supports two modes - (1) Real-time validation mode - validates each URL during content generation, ensuring zero broken links; (2) Post-validation mode - checks all footnotes in existing documents. Suitable for high-quality citation scenarios including web search data compilation, literature citation, and fact-checking tasks.

azure-pipelines-validator

16
from diegosouzapw/awesome-omni-skill

Comprehensive toolkit for validating, linting, and securing Azure DevOps Pipeline configurations.

ascii-diagram-validator

16
from diegosouzapw/awesome-omni-skill

Validate ASCII diagram alignment in markdown. TRIGGERS - diagram alignment, ASCII art, box-drawing diagrams.