Skip to main content
skill CX Codex

gsap · martinholovsky — Claude Code skill: GSAP animations for a HUD

A skill that teaches the agent GSAP animations: HUD panel entrances, status indicator transitions, scroll effects. Useful when the UI is built on Vue.

Install into Claude Code · Skills CLI (Vercel) All methods and platforms ↓
npx skills add martinholovsky/claude-skills-generator --skill gsap -a claude-code
Open on GitHub

What gsap does

The skill hands the agent GSAP (GreenSock Animation Platform) know-how plus ready patterns for a JARVIS HUD. The workflow is TDD: write the animation test first, implement the minimum, then refactor into a composable. Tests run on vitest with @vue/test-utils and cover panel entrance, animation cleanup on unmount, and the reduced motion path.

Patterns are split by scenario: panel entrance with gsap.from on opacity, y and scale; a status indicator driven by a timeline that switches on active, warning and error; bar chart animation. Scroll effects come through ScrollTrigger, registered in a Nuxt plugin. A references/ folder holds the advanced examples.

You need gsap at ^3.12.0 and @gsap/vue at the same version; ScrollTrigger ships with the core package. Kill tweens when a component unmounts — otherwise they stay in the global timeline and leak. A test asserting on gsap.globalTimeline.getChildren() catches that early.

What it helps with

  • animate HUD panel entrance and exit
  • switch a status indicator between active, warning and error
  • animate data bars on a chart
  • add scroll-triggered effects
  • verify in a test that animations are killed on unmount

Example prompts for the agent

  • write a panel entrance animation for HUDPanel with gsap
  • build a timeline for the status indicator with active and error states
  • add a vitest test that the animation is cleaned up on unmount

How to install gsap

1Skills CLI (Vercel)

npx skills add martinholovsky/claude-skills-generator --skill gsap -a claude-code

2Manually: put the files in place

~/.claude/skills/gsap/SKILL.md

Copy the whole skill folder; for one project use .claude/skills/gsap/

Step by step, with commands for each platform: How to install skills in Claude Code: five ways

Questions about gsap

How do I install gsap in Claude?

Run npx skills add martinholovsky/claude-skills-generator --skill gsap -a claude-code. The skill file lands at ~/.claude/skills/gsap/SKILL.md.

What does the gsap skill do?

It gives the agent GSAP patterns for a HUD: panel entrances, status indicator transitions, scroll effects. Work follows TDD, with the animation test written first.

Which GSAP versions does it need?

gsap and @gsap/vue at ^3.12.0; ScrollTrigger is included. Tests use vitest with @vue/test-utils.

Source text

SKILL.md · Unlicense
---
name: gsap
description: GSAP animations for JARVIS HUD transitions and effects
model: sonnet
risk_level: LOW
version: 1.0.0
---

# GSAP Animation Skill

> **File Organization**: This skill uses split structure. See `references/` for advanced patterns.

## 1. Overview

This skill provides GSAP (GreenSock Animation Platform) expertise for creating smooth, professional animations in the JARVIS AI Assistant HUD.

**Risk Level**: LOW - Animation library with minimal security surface

**Primary Use Cases**:
- HUD panel entrance/exit animations
- Status indicator transitions
- Data visualization animations
- Scroll-triggered effects
- Complex timeline sequences

## 2. Core Responsibilities

### 2.1 Fundamental Principles

1. **TDD First**: Write animation tests before implementation
2. **Performance Aware**: Use transforms/opacity for GPU acceleration, avoid layout thrashing
3. **Cleanup Required**: Always kill animations on component unmount
4. **Timeline Organization**: Use timelines for complex sequences
5. **Easing Selection**: Choose appropriate easing for HUD feel
6. **Accessibility**: Respect reduced motion preferences
7. **Memory Management**: Avoid memory leaks with proper cleanup

## 2.5 Implementation Workflow (TDD)

### Step 1: Write Failing Test First

```typescript
// tests/animations/panel-animation.test.ts
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'
import { mount } from '@vue/test-utils'
import { gsap } from 'gsap'
import HUDPanel from '~/components/HUDPanel.vue'

describe('HUDPanel Animation', () => {
  beforeEach(() => {
    // Mock reduced motion
    Object.defineProperty(window, 'matchMedia', {
      writable: true,
      value: vi.fn().mockImplementation(query => ({
        matches: false,
        media: query
      }))
    })
  })

  afterEach(() => {
    // Verify cleanup
    gsap.globalTimeline.clear()
  })

  it('animates panel entrance with correct properties', async () => {
    const wrapper = mount(HUDPanel)

    // Wait for animation to complete
    await new Promise(resolve => setTimeout(resolve, 600))

    const panel = wrapper.find('.hud-panel')
    expect(panel.exists()).toBe(true)
  })

  it('cleans up animations on unmount', async () => {
    const wrapper = mount(HUDPanel)
    const childCount = gsap.globalTimeline.getChildren().length

    await wrapper.unmount()

    // All animations should be killed
    expect(gsap.globalTimeline.getChildren().length).toBeLessThan(childCount)
  })

  it('respects reduced motion preference', async () => {
    // Mock reduced motion enabled
    window.matchMedia = vi.fn().mockImplementation(() => ({
      matches: true
    }))

    const wrapper = mount(HUDPanel)
    const panel = wrapper.find('.hud-panel').element

    // Should set final state immediately without animation
    expect(gsap.getProperty(panel, 'opacity')).toBe(1)
  })
})
```

### Step 2: Implement Minimum to Pass

```typescript
// components/HUDPanel.vue - implement animation logic
const animation = ref<gsap.core.Tween | null>(null)

onMounted(() => {
  if (!panelRef.value) return

  if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) {
    gsap.set(panelRef.value, { opacity: 1 })
    return
  }

  animation.value = gsap.from(panelRef.value, {
    opacity: 0,
    y: 20,
    duration: 0.5
  })
})

onUnmounted(() => {
  animation.value?.kill()
})
```

### Step 3: Refactor Following Patterns

```typescript
// Extract to composable for reusability
export function usePanelAnimation(elementRef: Ref<HTMLElement | null>) {
  const animation = ref<gsap.core.Tween | null>(null)

  const animate = () => {
    if (!elementRef.value) return

    if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) {
      gsap.set(elementRef.value, { opacity: 1 })
      return
    }

    animation.value = gsap.from(elementRef.value, {
      opacity: 0,
      y: 20,
      duration: 0.5,
      ease: 'power2.out'
    })
  }

  onMounted(animate)
  onUnmounted(() => animation.value?.kill())

  return { animation }
}
```

### Step 4: Run Full Verification

```bash
# Run animation tests
npm test -- --grep "Animation"

# Check for memory leaks
npm run test:memory

# Verify 60fps performance
npm run test:performance
```

## 3. Technology Stack & Versions

### 3.1 Recommended Versions

| Package | Version | Notes |
|---------|---------|-------|
| gsap | ^3.12.0 | Core library |
| @gsap/vue | ^3.12.0 | Vue integration |
| ScrollTrigger | included | Scroll effects |

### 3.2 Vue Integration

```typescript
// plugins/gsap.ts
import { gsap } from 'gsap'
import { ScrollTrigger } from 'gsap/ScrollTrigger'

export default defineNuxtPlugin(() => {
  gsap.registerPlugin(ScrollTrigger)

  return {
    provide: {
      gsap,
      ScrollTrigger
    }
  }
})
```

## 4. Implementation Patterns

### 4.1 Panel Entrance Animation

```vue
<script setup lang="ts">
import { gsap } from 'gsap'
import { onMounted, onUnmounted, ref } from 'vue'

const panelRef = ref<HTMLElement | null>(null)
let animation: gsap.core.Tween | null = null

onMounted(() => {
  if (!panelRef.value) return

  // ✅ Check reduced motion preference
  if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) {
    gsap.set(panelRef.value, { opacity: 1 })
    return
  }

  animation = gsap.from(panelRef.value, {
    opacity: 0,
    y: 20,
    scale: 0.95,
    duration: 0.5,
    ease: 'power2.out'
  })
})

// ✅ Cleanup on unmount
onUnmounted(() => {
  animation?.kill()
})
</script>

<template>
  <div ref="panelRef" class="hud-panel">
    <slot />
  </div>
</template>
```

### 4.2 Status Indicator Animation

```typescript
// composables/useStatusAnimation.ts
import { gsap } from 'gsap'

export function useStatusAnimation(element: Ref<HTMLElement | null>) {
  const timeline = ref<gsap.core.Timeline | null>(null)

  const animateStatus = (status: string) => {
    if (!element.value) return

    timeline.value?.kill()

    timeline.value = gsap.timeline()

    switch (status) {
      case 'active':
        timeline.value
          .to(element.value, {
            scale: 1.2,
            duration: 0.2,
            ease: 'power2.out'
          })
          .to(element.value, {
            scale: 1,
            duration: 0.3,
            ease: 'elastic.out(1, 0.3)'
          })
        break

      case 'warning':
        timeline.value.to(element.value, {
          backgroundColor: '#f59e0b',
          boxShadow: '0 0 10px #f59e0b',
          duration: 0.3,
          repeat: 2,
          yoyo: true
        })
        break

      case 'error':
        timeline.value.to(element.value, {
          x: -5,
          duration: 0.05,
          repeat: 5,
          yoyo: true
        })
        break
    }
  }

  onUnmounted(() => {
    timeline.value?.kill()
  })

  return { animateStatus }
}
```

### 4.3 Data Visualization Animation

```vue
<script setup lang="ts">
import { gsap } from 'gsap'

const props = defineProps<{
  data: number[]
}>()

const barsRef = ref<HTMLElement[]>([])
let animations: gsap.core.Tween[] = []

watch(() => props.data, (newData) => {
  // Kill previous animations
  animations.forEach(a => a.kill())
  animations = []

  // Animate each bar
  newData.forEach((value, index) => {
    const bar = barsRef.value[index]
    if (!bar) return

    const tween = gsap.to(bar, {
      height: `${value}%`,
      duration: 0.5,
      delay: index * 0.05,
      ease: 'power2.out'
    })

    animations.push(tween)
  })
}, { immediate: true })

onUnmounted(() => {
  animations.forEach(a => a.kill())
})
</script>

<template>
  <div class="flex items-end h-40 gap-1">
    <div
      v-for="(_, index) in data"
      :key="index"
      ref="barsRef"
      class="w-4 bg-jarvis-primary"
    />
  </div>
</template>
```

### 4.4 Timeline Sequence

```typescript
// Create complex HUD startup sequence
export function createStartupSequence(elements: {
  logo: HTMLElement
  panels: HTMLElement[]
  status: HTMLElement
}): gsap.core.Timeline {
  const tl = gsap.timeline({
    defaults: { ease: 'power2.out' }
  })

  // Logo reveal
  tl.from(elements.logo, {
    opacity: 0,
    scale: 0,
    duration: 0.8,
    ease: 'back.out(1.7)'
  })

  // Panels stagger in
  tl.from(elements.panels, {
    opacity: 0,
    x: -30,
    stagger: 0.1,
    duration: 0.5
  }, '-=0.3')

  // Status indicator
  tl.from(elements.status, {
    opacity: 0,
    y: 10,
    duration: 0.3
  }, '-=0.2')

  return tl
}
```

### 4.5 Scroll-Triggered Animation

```vue
<script setup lang="ts">
import { gsap } from 'gsap'
import { ScrollTrigger } from 'gsap/ScrollTrigger'

const sectionRef = ref<HTMLElement | null>(null)

onMounted(() => {
  if (!sectionRef.value) return

  gsap.from(sectionRef.value.querySelectorAll('.animate-item'), {
    scrollTrigger: {
      trigger: sectionRef.value,
      start: 'top 80%',
      end: 'bottom 20%',
      toggleActions: 'play none none reverse'
    },
    opacity: 0,
    y: 30,
    stagger: 0.1,
    duration: 0.5
  })
})

onUnmounted(() => {
  ScrollTrigger.getAll().forEach(trigger => trigger.kill())
})
</script>
```

## 5. Quality Standards

### 5.1 Performance

```typescript
// ✅ GOOD - Use transforms for GPU acceleration
gsap.to(element, {
  x: 100,
  y: 50,
  rotation: 45,
  scale: 1.2
})

// ❌ BAD - Triggers layout recalculation
gsap.to(element, {
  left: 100,
  top: 50,
  width: '120%'
})
```

### 5.2 Accessibility

```typescript
// ✅ Respect reduced motion
const prefersReducedMotion = window.matchMedia(
  '(prefers-reduced-motion: reduce)'
).matches

if (prefersReducedMotion) {
  gsap.set(element, { opacity: 1 })
} else {
  gsap.from(element, { opacity: 0, duration: 0.5 })
}
```

## 6. Performance Patterns

### 6.1 will-change Property Usage

```typescript
// Good: Apply will-change before animation
const animatePanel = (element: HTMLElement) => {
  element.style.willChange = 'transform, opacity'

  gsap.to(element, {
    x: 100,
    opacity: 0.8,
    duration: 0.5,
    onComplete: () => {
      element.style.willChange = 'auto'
    }
  })
}

// Bad: Never removing will-change
const animatePanelBad = (element: HTMLElement) => {
  element.style.willChange = 'transform, opacity' // Memory leak!
  gsap.to(element, { x: 100, opacity: 0.8 })
}
```

### 6.2 Transform vs Layout Properties

```typescript
// Good: Use transforms (GPU accelerated)
gsap.to(element, {
  x: 100,           // translateX
  y: 50,            // translateY
  scale: 1.2,       // scale
  rotation: 45,     // rotate
  opacity: 0.5      // opacity
})

// Bad: Layout-triggering properties (CPU, causes reflow)
gsap.to(element, {
  left: 100,        // Triggers layout
  top: 50,          // Triggers layout
  width: '120%',    // Triggers layout
  height: 200,      // Triggers layout
  margin: 10        // Triggers layout
})
```

### 6.3 Timeline Reuse

```typescript
// Good: Reuse timeline instance
const timeline = gsap.timeline({ paused: true })
timeline
  .to(element, { opacity: 1, duration: 0.3 })
  .to(element, { y: -20, duration: 0.5 })

// Play/reverse as needed
const show = () => timeline.play()
const hide = () => timeline.reverse()

// Bad: Creating new timeline each time
const showBad = () => {
  gsap.timeline()
    .to(element, { opacity: 1, duration: 0.3 })
    .to(element, { y: -20, duration: 0.5 })
}
```

### 6.4 ScrollTrigger Batching

```typescript
// Good: Batch ScrollTrigger animations
ScrollTrigger.batch('.animate-item', {
  onEnter: (elements) => {
    gsap.to(elements, {
      opacity: 1,
      y: 0,
      stagger: 0.1,
      overwrite: true
    })
  },
  onLeave: (elements) => {
    gsap.to(elements, {
      opacity: 0,
      y: -20,
      overwrite: true
    })
  }
})

// Bad: Individual ScrollTrigger per element
document.querySelectorAll('.animate-item').forEach(item => {
  gsap.to(item, {
    scrollTrigger: {
      trigger: item,
      start: 'top 80%'
    },
    opacity: 1,
    y: 0
  })
})
```

### 6.5 Lazy Initialization

```typescript
// Good: Initialize animations only when needed
let panelAnimation: gsap.core.Timeline | null = null

const getPanelAnimation = () => {
  if (!panelAnimation) {
    panelAnimation = gsap.timeline({ paused: true })
      .from('.panel', { opacity: 0, y: 20 })
      .from('.panel-content', { opacity: 0, stagger: 0.1 })
  }
  return panelAnimation
}

const showPanel = () => getPanelAnimation().play()
const hidePanel = () => getPanelAnimation().reverse()

// Bad: Initialize all animations on mount
onMounted(() => {
  // Creates timeline even if never used
  const animation1 = gsap.timeline().to('.panel1', { x: 100 })
  const animation2 = gsap.timeline().to('.panel2', { y: 100 })
  const animation3 = gsap.timeline().to('.panel3', { scale: 1.2 })
})
```

## 7. Testing & Quality

### 7.1 Animation Testing

```typescript
describe('Panel Animation', () => {
  it('cleans up on unmount', async () => {
    const wrapper = mount(HUDPanel)
    await wrapper.unmount()

    // No active GSAP animations should remain
    expect(gsap.globalTimeline.getChildren().length).toBe(0)
  })
})
```

## 8. Common Mistakes & Anti-Patterns

### 8.1 Critical Anti-Patterns

#### Never: Skip Cleanup

```typescript
// ❌ MEMORY LEAK
onMounted(() => {
  gsap.to(element, { x: 100, duration: 1 })
})

// ✅ PROPER CLEANUP
let tween: gsap.core.Tween

onMounted(() => {
  tween = gsap.to(element, { x: 100, duration: 1 })
})

onUnmounted(() => {
  tween?.kill()
})
```

#### Never: Animate Layout Properties

```typescript
// ❌ BAD - Causes layout thrashing
gsap.to(element, { width: 200, height: 100 })

// ✅ GOOD - Use transforms
gsap.to(element, { scaleX: 2, scaleY: 1 })
```

## 13. Pre-Implementation Checklist

### Phase 1: Before Writing Code

- [ ] Write failing tests for animation behavior
- [ ] Define animation timing and easing requirements
- [ ] Identify elements that need will-change hints
- [ ] Plan cleanup strategy for all animations
- [ ] Check if reduced motion support is needed

### Phase 2: During Implementation

- [ ] Use transforms/opacity only (no layout properties)
- [ ] Store animation references for cleanup
- [ ] Apply will-change before, remove after animation
- [ ] Use timelines for sequences
- [ ] Batch ScrollTrigger animations
- [ ] Implement lazy initialization for complex animations

### Phase 3: Before Committing

- [ ] All tests pass (npm test -- --grep "Animation")
- [ ] All animations cleaned up on unmount
- [ ] Reduced motion preference respected
- [ ] No memory leaks (check with DevTools)
- [ ] 60fps maintained (test with performance monitor)
- [ ] ScrollTrigger instances properly killed

## 14. Summary

GSAP provides professional animations for JARVIS HUD:

1. **Cleanup**: Always kill animations on unmount
2. **Performance**: Use transforms and opacity only
3. **Accessibility**: Respect reduced motion preference
4. **Organization**: Use timelines for sequences

**Remember**: Every animation must be cleaned up to prevent memory leaks.

---

**References**:
- `references/advanced-patterns.md` - Complex animation patterns

© martinholovsky · Unlicense · martinholovsky/claude-skills-generator

Similar skills

Everything for Frontend and UI →

gsap by other authors comes first.

gsap MengTo A skill that helps your coding agent write and debug GSAP web animations: timelines, ScrollTrigger, stagger, transforms. CX Codex +1 1,800installs gsap AThevon This skill helps an agent write GSAP animations with timelines, staggered effects, and ScrollTrigger. Use it for complex motion and scroll-linked scenes. CX Codex +1 997installs gsap Mindrally Tells your agent how to write GSAP animations: transforms over left/top, stagger, timelines, ScrollTrigger. Useful when the UI stutters on weaker hardware. CX Codex +1 769installs gsap official HeyGen A GSAP cheat sheet for your agent: tweens, timelines, easing, performance. Useful when writing animation inside HyperFrames compositions. CX Codex GP ChatGPT 3installs gsap-plugins greensock A skill that walks your agent through GSAP plugin registration and usage: ScrollTo, Flip, Draggable, SplitText and more. Handy when your animations already run on GSAP. CX Codex +1 67,200installs gsap-frameworks greensock Official GSAP skill for Vue, Nuxt, Svelte and SvelteKit. Tells the agent where to create animations and how to clean them up on unmount. CX Codex +1 62,500installs gsap-scrolltrigger freshtechbro A skill that teaches the agent to write GSAP animations and ScrollTrigger scroll effects: tweens, timelines, pinning, parallax. CX Codex +1 2,800installs cinematic-gsap-lenis-motion-system MengTo Builds cinematic web animation systems using GSAP, ScrollTrigger, and Lenis. Ideal for luxury editorial layouts, creative portfolios, and smooth reveals. CX Codex +1 2,400installs gsap-scrolltrigger-storytelling MengTo A skill for scroll-driven product storytelling: pinned scenes, progressive UI reveals and transitions between sections, built on GSAP ScrollTrigger. CX Codex +1 1,800installs gsap-react Bbeierle12 A skill with GSAP patterns for React: the useGSAP hook, ref handling, cleanup on unmount and timeline control. CX Codex +1 724installs

From the same set15

SQLite Database Expert Guides local SQLite embedded database development for Rust and Tauri desktop applications with parameterized queries, FTS5 search, and WAL performance tuning. CX Codex +1 3,100installs windows-ui-automation A skill for automating Windows apps through UI Automation and Win32 APIs: element discovery, input simulation, process interaction. Risk level HIGH. CX Codex +1 1,300installs cicd-expert A skill for building CI/CD: GitHub Actions, GitLab CI, Jenkins, security gates and ArgoCD GitOps. Useful when a pipeline needs writing or fixing. CX Codex +1 645installs webgl A WebGL skill for custom shaders and visual effects: holograms, post-processing, particle systems. Useful when you're building a 3D interface. CX Codex +1 555installs tailwindcss A skill that teaches AI agents to style the JARVIS assistant UI with Tailwind utility classes: dark HUD theme, responsive grids, animations, and tests before implementation. CX Codex +1 498installs rabbitmq-expert A skill that turns your AI agent into a RabbitMQ admin and developer: exchange patterns, clustering, high availability, production monitoring. Useful when you design queues or debug a cluster. CX Codex +1 491installs celery-expert Guides background job design on Celery: retries, chains, groups, chords, Celery Beat schedules and Flower monitoring. CX Codex +1 454installs wake-word-detection A skill for building wake word detection on openWakeWord: local audio monitoring, no cloud calls. Useful when you are wiring up a JARVIS-style assistant. CX Codex +1 404installs

Project sponsors

Companies that keep this analytics open
Gold sponsor

Impressions, clicks and code copies — open statistics. We keep the numbers public for the same reason NeBlask itself is public. Become a sponsor