Composables
Animations Utilities
Create animation utilities for continuous motion effects and keyframe-based animations with full type safety.
Overview
Animation utilities help you create continuous motion effects and keyframe-based animations. These utilities let you define and apply CSS animations for loading indicators, attention-grabbing effects, and other repeating or complex motion patterns.
Why Use Animation Utilities?
Animation utilities help you:
- Create motion effects: Build loading spinners, pulsing indicators, and bouncing elements
- Define reusable animations: Register keyframe animations once and apply them as utility classes
- Maintain consistency: Use the same animation patterns across your application
- Improve user experience: Guide attention with purposeful motion
useAnimationUtility
The useAnimationUtility() function creates utility classes for applying CSS animations.
styleframe.config.ts
import { styleframe } from "styleframe";
import { useAnimationUtility } from "@styleframe/theme";
const s = styleframe();
const { keyframes, css } = s;
// Define keyframes
const spin = keyframes('spin', {
'from': { transform: 'rotate(0deg)' },
'to': { transform: 'rotate(360deg)' },
});
const ping = keyframes('ping', {
'75%, 100%': { transform: 'scale(2)', opacity: '0' },
});
const pulse = keyframes('pulse', {
'0%, 100%': { opacity: '1' },
'50%': { opacity: '.5' },
});
const bounce = keyframes('bounce', {
'0%, 100%': { transform: 'translateY(-25%)', animationTimingFunction: 'cubic-bezier(0.8, 0, 1, 1)' },
'50%': { transform: 'translateY(0)', animationTimingFunction: 'cubic-bezier(0, 0, 0.2, 1)' },
});
useAnimationUtility(s, {
none: 'none',
spin: css`${spin} 1s linear infinite`,
ping: css`${ping} 1s cubic-bezier(0, 0, 0.2, 1) infinite`,
pulse: css`${pulse} 2s cubic-bezier(0.4, 0, 0.6, 1) infinite`,
bounce: css`${bounce} 1s infinite`,
});
export default s;
styleframe/index.css
@keyframes spin {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
@keyframes ping {
75%, 100% { transform: scale(2); opacity: 0; }
}
@keyframes pulse {
0%, 100% { opacity: 1; }
50% { opacity: .5; }
}
@keyframes bounce {
0%, 100% { transform: translateY(-25%); animation-timing-function: cubic-bezier(0.8, 0, 1, 1); }
50% { transform: translateY(0); animation-timing-function: cubic-bezier(0, 0, 0.2, 1); }
}
._animation\:none { animation: none; }
._animation\:spin { animation: spin 1s linear infinite; }
._animation\:ping { animation: ping 1s cubic-bezier(0, 0, 0.2, 1) infinite; }
._animation\:pulse { animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite; }
._animation\:bounce { animation: bounce 1s infinite; }
<svg class="_animation:spin"><!-- Loading spinner --></svg>
<span class="_animation:ping"><!-- Notification dot --></span>
<div class="_animation:pulse"><!-- Skeleton loader --></div>
<div class="_animation:bounce"><!-- Bouncing element --></div>
Examples
Loading Spinner
styleframe.config.ts
import { styleframe } from "styleframe";
import { useAnimationUtility } from "@styleframe/theme";
const s = styleframe();
const { keyframes, css } = s;
const spin = keyframes('spin', {
'from': { transform: 'rotate(0deg)' },
'to': { transform: 'rotate(360deg)' },
});
useAnimationUtility(s, {
spin: css`${spin} 1s linear infinite`,
});
export default s;
styleframe/index.css
@keyframes spin {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
._animation\:spin { animation: spin 1s linear infinite; }
Usage in HTML:
<svg class="_animation:spin" width="24" height="24">
<circle cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4" fill="none" />
</svg>
Best Practices
- Use purposeful animation: Animations should enhance UX, not distract
- Respect reduced motion: Consider users who prefer reduced motion
- Avoid animating layout: Prefer transform and opacity for performance
- Be consistent: Use the same animation patterns across similar interactions
- Define keyframes alongside animations: Keep keyframe definitions close to where they're used for maintainability
FAQ
Use animations for continuous or complex motion (loading spinners, attention-grabbing effects). Use transitions for state changes (hover, focus, active). Animations can run independently; transitions are triggered by state changes.
Use the
prefers-reduced-motion media query to disable or reduce animations. Consider creating a modifier that respects this preference, or set animation: none globally for these users.