micro-interaction-adder
$npx skills add blunotech-dev/skills --skill micro-interaction-adderInjects polished CSS micro-interactions into existing or new frontend code — hover scales, focus rings, button press feedback, link underlines, card lifts, ripple effects, skeleton loaders, and more. Use this skill whenever the user asks to "add animations", "make it feel more interactive", "add hover effects", "improve UX polish", "add transitions", "make buttons feel better", or anytime existing UI code looks static or unresponsive. Trigger even when the user hasn't said "micro-interaction" explicitly — phrases like "feels dead", "too plain", "make it snappier", "improve feel", or "add some life to it" are all strong signals. Combine with the frontend-design skill when building from scratch.
Micro-Interaction Adder
This skill layers production-grade CSS micro-interactions onto frontend code — new or existing. The goal: every element a user touches should respond, making the interface feel alive, crafted, and trustworthy.
Philosophy
Micro-interactions are not decoration. They:
- Confirm intent — "yes, I saw you click that"
- Communicate state — loading, disabled, selected, error
- Reward attention — subtle delight for the observant
- Establish hierarchy — animated elements feel more important
Rules of thumb:
- Duration:
150–300msfor most UI.400–600msfor entrances. Never over800msfor interactive feedback. - Easing: prefer
cubic-beziercurves overease-in-outdefaults. Use spring-feel curves for scale. - Less is more: one well-executed hover beats five mediocre ones. Pick the 3–5 highest-impact moments.
- Respect
prefers-reduced-motion— always wrap animation-heavy CSS in the appropriate media query.
1. Audit the UI
Before adding anything, scan the code for:
- Interactive elements (buttons, links, inputs, checkboxes, cards, nav items)
- State-bearing elements (loading, error, success, disabled)
- Structural elements that could benefit from entrance animations (modals, dropdowns, toasts)
2. Select Interaction Patterns
Choose from the Pattern Library below. Don't apply everything — pick what fits the component's purpose and the overall aesthetic (see references/pattern-library.md for full recipes).
3. Inject the CSS
- Add transitions to base state, NOT to
:hover/:focusstate. This ensures smooth exit animations too. - Use CSS custom properties (
--transition-fast,--color-focus-ring) for consistency. - Keep interaction CSS co-located with component styles, not in a separate "animations.css" blob.
4. Validate
Check:
- [ ] Interactions work on keyboard focus (
:focus-visible), not just mouse hover - [ ] Disabled states suppress all transitions (
pointer-events: none; opacity: 0.5) - [ ]
prefers-reduced-motionfallback exists for all scale/translate animations - [ ] No layout shifts — use
transformandopacityonly (GPU-composited)
Core CSS Variables (inject into `:root`)
:root {
/* Timing */
--duration-instant: 100ms;
--duration-fast: 150ms;
--duration-base: 200ms;
--duration-slow: 300ms;
--duration-enter: 400ms;
/* Easing */
--ease-out: cubic-bezier(0.0, 0.0, 0.2, 1);
--ease-in-out: cubic-bezier(0.4, 0.0, 0.2, 1);
--ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1); /* slight overshoot */
--ease-snappy: cubic-bezier(0.25, 0.46, 0.45, 0.94);
/* Focus ring */
--color-focus-ring: #3b82f6; /* adjust to brand color */
--focus-ring-width: 3px;
--focus-ring-offset: 2px;
/* Shadows for lift effects */
--shadow-resting: 0 1px 3px rgba(0,0,0,0.12), 0 1px 2px rgba(0,0,0,0.08);
--shadow-hover: 0 4px 12px rgba(0,0,0,0.15), 0 2px 6px rgba(0,0,0,0.10);
--shadow-active: 0 1px 2px rgba(0,0,0,0.10);
}
Pattern Library (Quick Reference)
Full recipes with variants are in references/pattern-library.md.
| Pattern | Elements | Key Properties |
|----------------------|---------------------------------|---------------------------------------|
| Hover Scale | Cards, images, avatars | transform: scale(1.03) |
| Button Press | All buttons | scale(0.96) on :active |
| Focus Ring | Inputs, buttons, links | outline + box-shadow on :focus-visible |
| Link Underline Sweep | <a> tags, nav items | background-size pseudo-element trick |
| Card Lift | Content cards | transform: translateY(-3px) + shadow |
| Icon Wiggle | Icon-only buttons, alerts | @keyframes wiggle on hover |
| Checkbox Spring | Custom checkboxes | scale + opacity on check state |
| Input Focus Expand | Text inputs, textareas | border-color + box-shadow glow |
| Skeleton Loader | Loading states | @keyframes shimmer gradient sweep |
| Fade + Slide Entrance| Modals, dropdowns, toasts | opacity + translateY on mount |
| Ripple Effect | Buttons (Material-style) | Pseudo-element radial expand |
| Toggle Switch | Boolean toggles | Smooth translateX + color shift |
| Progress Bar Fill | Upload, step indicators | width + background transition |
| Tooltip Appear | Tooltips, popovers | opacity + scale(0.95) origin |
Accessibility: `prefers-reduced-motion`
Always include this block when using scale, translate, or entrance animations:
@media (prefers-reduced-motion: reduce) {
*, *::before, *::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
}
}
For interactions that still need some feedback (e.g., focus rings, color changes), leave
color, background-color, border-color, and opacity transitions intact — only strip
transform and motion-heavy @keyframes.
Plain HTML/CSS
- Use the raw CSS patterns from
references/pattern-library.mddirectly. - Add
will-change: transformto frequently animated elements (use sparingly).
React
- For entrance animations on mount/unmount, use CSS classes +
useStatetoggle, or themotionlibrary (framer-motion). Seereferences/react-patterns.md. - Avoid
useEffect+setTimeouthacks for animations — use CSS@keyframeswith a class toggle instead. transition-allis a code smell — always specify the property explicitly.
Tailwind CSS
- Use
transition,duration-{n},ease-{type},hover:scale-{n},active:scale-{n},focus-visible:ring-{n}utilities. - For custom cubic-bezier curves, extend
tailwind.config.jstransitionTimingFunction. - For entrance animations not in core Tailwind, write a thin
@layer utilitiesblock.
Vue / Svelte
- Use
<Transition>(Vue) ortransition:directive (Svelte) for enter/leave. - CSS custom properties approach works identically.
Common Mistakes to Avoid
| ❌ Mistake | ✅ Fix |
|-----------------------------------------|--------------------------------------------------|
| transition: all 0.3s | Specify only changed properties |
| Putting transition on :hover only | Put on base state for smooth exit |
| transform + position: fixed combo | Creates new stacking context — test carefully |
| box-shadow transitions on many items | Expensive — prefer filter: drop-shadow or pseudo-element shadow |
| Forgetting focus-visible | Don't style :focus alone — it fires on click |
| animation: spin infinite in lists | Decimates performance — use will-change sparingly |
Read Next
references/pattern-library.md— Full copy-paste CSS for every pattern in the table above, with light/dark variants and customization notes.references/react-patterns.md— React-specific hooks,framer-motionsnippets, and class-toggle entrance patterns.