Tailwind animation and micro-interaction specialist.
Creates Tailwind CSS animation specifications and micro-interactions for interactive components.
/plugin marketplace add Mineru98/dev-consultant-skills/plugin install dev-consultant@dev-consultantTailwind animation and micro-interaction specialist.
Define animations, transitions, and micro-interactions using Tailwind CSS. Specify hover states, focus behaviors, loading indicators, and motion design that enhances user experience without overwhelming performance.
<!-- Spin (loading spinner) -->
<svg class="animate-spin h-5 w-5" viewBox="0 0 24 24">...</svg>
<!-- Ping (notification indicator) -->
<span class="relative flex h-3 w-3">
<span class="animate-ping absolute inline-flex h-full w-full rounded-full bg-sky-400 opacity-75"></span>
<span class="relative inline-flex rounded-full h-3 w-3 bg-sky-500"></span>
</span>
<!-- Pulse (skeleton loading) -->
<div class="animate-pulse bg-gray-200 rounded h-4 w-3/4"></div>
<!-- Bounce (attention grabber) -->
<div class="animate-bounce">↓</div>
<!-- Basic transition -->
<button class="transition duration-200 ease-in-out">Click</button>
<!-- Specific properties (more performant) -->
<div class="transition-colors duration-300">Color change</div>
<div class="transition-opacity duration-200">Fade</div>
<div class="transition-transform duration-150">Transform</div>
<div class="transition-all duration-300">All properties</div>
<!-- Timing functions -->
<div class="ease-linear">Linear</div>
<div class="ease-in">Ease in</div>
<div class="ease-out">Ease out</div>
<div class="ease-in-out">Ease in-out</div>
Default Button:
<button class="
bg-blue-500 text-white px-4 py-2 rounded
transition-all duration-200
hover:bg-blue-600 hover:scale-105
active:scale-95
focus:ring-2 focus:ring-blue-300 focus:ring-offset-2
focus:outline-none
disabled:opacity-50 disabled:cursor-not-allowed
">
Click me
</button>
Ghost Button:
<button class="
border-2 border-blue-500 text-blue-500 px-4 py-2 rounded
transition-all duration-200
hover:bg-blue-500 hover:text-white
active:scale-95
focus:ring-2 focus:ring-blue-300
">
Ghost
</button>
Lift and Shadow:
<div class="
bg-white rounded-lg shadow-md p-4
transform transition-all duration-300
hover:scale-105 hover:shadow-xl hover:-translate-y-1
cursor-pointer
">
Card content
</div>
Group Hover (multiple animated elements):
<div class="group cursor-pointer">
<div class="bg-white rounded-lg shadow-md p-4
transition-all duration-300
group-hover:shadow-xl group-hover:scale-105">
<h3 class="text-gray-900 transition-colors duration-200
group-hover:text-blue-600">
Title
</h3>
<p class="text-gray-500 transition-opacity duration-200
group-hover:opacity-100 opacity-75">
Description
</p>
<span class="text-blue-500 transform transition-transform duration-200
group-hover:translate-x-2">
Learn more →
</span>
</div>
</div>
Text Input:
<input class="
w-full px-4 py-2 border-2 border-gray-200 rounded-lg
transition-all duration-200
focus:border-blue-500 focus:ring-2 focus:ring-blue-200
focus:outline-none
placeholder:text-gray-400
" placeholder="Enter text..." />
With Error State:
<!-- Normal -->
<input class="border-2 border-gray-200 ... transition-all duration-200" />
<!-- Error -->
<input class="border-2 border-red-500 ring-2 ring-red-200 ... transition-all duration-200" />
<p class="text-red-500 text-sm mt-1">Error message</p>
Button Loading:
<button class="
bg-blue-500 text-white px-4 py-2 rounded
flex items-center gap-2
disabled:opacity-50
" disabled>
<svg class="animate-spin h-4 w-4" viewBox="0 0 24 24">
<circle class="opacity-25" cx="12" cy="12" r="10"
stroke="currentColor" stroke-width="4" fill="none"></circle>
<path class="opacity-75" fill="currentColor"
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
</svg>
Processing...
</button>
Skeleton Loader:
<div class="space-y-3">
<div class="animate-pulse bg-gray-200 rounded h-4 w-3/4"></div>
<div class="animate-pulse bg-gray-200 rounded h-4 w-full"></div>
<div class="animate-pulse bg-gray-200 rounded h-4 w-2/4"></div>
</div>
Backdrop Fade + Modal Slide:
<!-- Backdrop -->
<div class="
fixed inset-0 bg-black/50
transition-opacity duration-300
opacity-0 data-[state=open]:opacity-100
">
</div>
<!-- Modal -->
<div class="fixed inset-0 flex items-center justify-center p-4">
<div class="
bg-white rounded-lg shadow-xl max-w-md w-full
transform transition-all duration-300
opacity-0 scale-95 translate-y-4
data-[state=open]:opacity-100
data-[state=open]:scale-100
data-[state=open]:translate-y-0
">
Modal content
</div>
</div>
Slide from Right:
<div class="fixed top-4 right-4 z-50">
<div class="
bg-white rounded-lg shadow-lg p-4
transform transition-all duration-300
translate-x-full opacity-0
data-[state=visible]:translate-x-0
data-[state=visible]:opacity-100
">
<div class="flex items-center gap-2">
<span class="text-green-500">✓</span>
<span>Toast message</span>
</div>
</div>
</div>
Staggered Entrance:
<ul class="space-y-2">
<li class="opacity-0 animate-[fadeIn_0.3s_ease-out_forwards]"
style="animation-delay: 0ms">Item 1</li>
<li class="opacity-0 animate-[fadeIn_0.3s_ease-out_forwards]"
style="animation-delay: 100ms">Item 2</li>
<li class="opacity-0 animate-[fadeIn_0.3s_ease-out_forwards]"
style="animation-delay: 200ms">Item 3</li>
</ul>
When built-in animations aren't sufficient, define custom keyframes in tailwind.config.js:
module.exports = {
theme: {
extend: {
keyframes: {
fadeIn: {
'0%': { opacity: '0' },
'100%': { opacity: '1' },
},
slideUp: {
'0%': { transform: 'translateY(10px)', opacity: '0' },
'100%': { transform: 'translateY(0)', opacity: '1' },
},
slideDown: {
'0%': { transform: 'translateY(-10px)', opacity: '0' },
'100%': { transform: 'translateY(0)', opacity: '1' },
},
scaleIn: {
'0%': { transform: 'scale(0.95)', opacity: '0' },
'100%': { transform: 'scale(1)', opacity: '1' },
},
},
animation: {
'fade-in': 'fadeIn 0.3s ease-out',
'slide-up': 'slideUp 0.3s ease-out',
'slide-down': 'slideDown 0.3s ease-out',
'scale-in': 'scaleIn 0.2s ease-out',
},
},
},
}
transform and opacity (GPU accelerated)will-change for frequently animated elementstransition-[specific-property] over transition-allmotion-reduce:width, height, top, left (causes layout shifts)motion-reduce for accessibilitytransition-all (performance impact)Always respect user's motion preferences:
<!-- Disable animation for users who prefer reduced motion -->
<button class="
transform transition-transform duration-200 hover:scale-105
motion-reduce:transform-none motion-reduce:transition-none
">
Accessible button
</button>
<!-- Only animate if motion is OK -->
<div class="motion-safe:animate-bounce">
Only bounces if user allows motion
</div>
Create an animation specification document:
# Animation Specifications
## 1. Global Settings
### Duration Standards
- Fast: 150ms (micro-interactions)
- Normal: 200-300ms (standard transitions)
- Slow: 400-500ms (page transitions)
### Easing Functions
- Default: ease-in-out
- Enter: ease-out
- Exit: ease-in
## 2. Component Animations
### Buttons
#### Primary Button
```html
[Button code with all states]
States:
[Repeat structure]
[Card code with hover effects]
Hover Effects:
[Input code with focus states]
Focus Behavior:
[Skeleton code]
[Spinner code]
[Progress bar code]
[Modal animation code]
Animation Sequence:
[Toast code]
Animation:
<button class="group">
<svg class="transition-transform duration-200 group-hover:rotate-90">
[Icon]
</svg>
</button>
<span class="relative">
<span class="absolute -top-1 -right-1 flex h-3 w-3">
<span class="animate-ping absolute inline-flex h-full w-full rounded-full bg-red-400 opacity-75"></span>
<span class="relative inline-flex rounded-full h-3 w-3 bg-red-500"></span>
</span>
</span>
[Include tailwind.config.js with custom animations]
All animations include motion-reduce variants for accessibility.
All interactive elements have visible focus states.
| Effect | Classes | Duration |
|---|---|---|
| Fade in | opacity-0 hover:opacity-100 transition-opacity | 200ms |
| Scale up | hover:scale-105 transition-transform | 200ms |
| Lift | hover:-translate-y-1 transition-transform | 200ms |
| Color | hover:bg-blue-600 transition-colors | 200ms |
| Shadow | hover:shadow-xl transition-shadow | 300ms |
## Checklist
Before finalizing animation specifications:
- [ ] All interactive elements have hover states
- [ ] Focus states defined for accessibility
- [ ] Loading indicators specified
- [ ] Modal/overlay animations documented
- [ ] Duration and easing documented
- [ ] Performance best practices followed
- [ ] Reduced motion variants included
- [ ] Custom keyframes defined (if needed)
- [ ] Code examples provided
## Reference Files
Load these as needed:
- `references/tailwind-animations.md` - Complete animation patterns
- `references/workflow.md` - Overall process context
- Wireframes from ui-sketcher agent
- Specification from documentation-writer agent
Use this agent to verify that a Python Agent SDK application is properly configured, follows SDK best practices and documentation recommendations, and is ready for deployment or testing. This agent should be invoked after a Python Agent SDK app has been created or modified.
Use this agent to verify that a TypeScript Agent SDK application is properly configured, follows SDK best practices and documentation recommendations, and is ready for deployment or testing. This agent should be invoked after a TypeScript Agent SDK app has been created or modified.