Animation Utilities
Advanced animation utilities and helpers for FoundryKit animations
Animation Utilities
Learn how to use advanced animation utilities and helpers to create complex, performant animations.
Custom Animation Hooks
useAnimationSequence
Create complex animation sequences with precise timing control.
import { useAnimationSequence } from '@foundrykit/animation'
import { useState } from 'react'
function AnimationSequence() {
const [isVisible, setIsVisible] = useState(false)
const sequence = useAnimationSequence([
{
key: 'title',
animation: 'fadeIn',
delay: 0,
duration: 0.6
},
{
key: 'subtitle',
animation: 'slideUp',
delay: 0.3,
duration: 0.5
},
{
key: 'button',
animation: 'scale',
delay: 0.6,
duration: 0.4
}
])
return (
<div className="space-y-4">
<button onClick={() => setIsVisible(!isVisible)}>
{isVisible ? 'Hide' : 'Show'} Sequence
</button>
{isVisible && (
<div className="space-y-4">
<div className={sequence.title}>
<h1 className="text-3xl font-bold">Welcome</h1>
</div>
<div className={sequence.subtitle}>
<p className="text-lg text-gray-600">This is a subtitle</p>
</div>
<div className={sequence.button}>
<button className="px-4 py-2 bg-blue-600 text-white rounded">
Action Button
</button>
</div>
</div>
)}
</div>
)
}
useStaggeredAnimation
Create staggered animations with custom timing and easing.
import { useStaggeredAnimation } from '@foundrykit/animation'
function StaggeredList() {
const items = ['Item 1', 'Item 2', 'Item 3', 'Item 4', 'Item 5']
const staggeredProps = useStaggeredAnimation({
items,
animation: 'slideUp',
staggerDelay: 0.1,
duration: 0.5,
easing: 'ease-out'
})
return (
<div className="space-y-2">
{items.map((item, index) => (
<div key={index} className={staggeredProps[index]}>
<div className="p-4 bg-gray-100 rounded">
{item}
</div>
</div>
))}
</div>
)
}
useIntersectionAnimation
Trigger animations when elements come into view.
import { useIntersectionAnimation } from '@foundrykit/animation'
function IntersectionTriggered() {
const fadeInProps = useIntersectionAnimation({
animation: 'fadeIn',
threshold: 0.1,
duration: 0.6
})
const slideUpProps = useIntersectionAnimation({
animation: 'slideUp',
threshold: 0.2,
duration: 0.8
})
return (
<div className="space-y-8">
<div className={fadeInProps}>
<h2 className="text-2xl font-bold">Fade In on Scroll</h2>
<p>This content will fade in when it comes into view.</p>
</div>
<div className={slideUpProps}>
<h2 className="text-2xl font-bold">Slide Up on Scroll</h2>
<p>This content will slide up when it comes into view.</p>
</div>
</div>
)
}
Animation Presets
Predefined Animation Sequences
Use predefined animation sequences for common patterns.
import { animationPresets } from '@foundrykit/animation'
function PresetAnimations() {
const heroSequence = animationPresets.hero()
const cardSequence = animationPresets.card()
const listSequence = animationPresets.list()
return (
<div className="space-y-8">
{/* Hero section with preset */}
<div className="text-center py-12">
<div className={heroSequence.title}>
<h1 className="text-4xl font-bold mb-4">Welcome</h1>
</div>
<div className={heroSequence.subtitle}>
<p className="text-xl text-gray-600 mb-6">Subtitle text</p>
</div>
<div className={heroSequence.cta}>
<button className="px-6 py-3 bg-blue-600 text-white rounded">
Get Started
</button>
</div>
</div>
{/* Card grid with preset */}
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
{[1, 2, 3].map((index) => (
<div key={index} className={cardSequence[index - 1]}>
<div className="p-6 bg-white rounded-lg shadow">
<h3 className="text-lg font-semibold mb-2">Card {index}</h3>
<p className="text-gray-600">Card content</p>
</div>
</div>
))}
</div>
{/* List with preset */}
<div className="space-y-2">
{['Item 1', 'Item 2', 'Item 3'].map((item, index) => (
<div key={index} className={listSequence[index]}>
<div className="p-4 bg-gray-100 rounded">
{item}
</div>
</div>
))}
</div>
</div>
)
}
Custom Animation Presets
Create your own animation presets for consistent patterns.
import { createAnimationPreset } from '@foundrykit/animation'
// Create a custom preset for dashboard widgets
const dashboardPreset = createAnimationPreset({
name: 'dashboard',
animations: [
{
key: 'header',
animation: 'fadeIn',
delay: 0,
duration: 0.6
},
{
key: 'widgets',
animation: 'slideUp',
staggerDelay: 0.1,
duration: 0.5
},
{
key: 'sidebar',
animation: 'slideIn',
delay: 0.3,
duration: 0.7
}
]
})
function DashboardWithPreset() {
const dashboard = dashboardPreset()
return (
<div className="flex">
{/* Sidebar */}
<div className={dashboard.sidebar}>
<div className="w-64 bg-gray-100 p-4">
<h3 className="font-semibold mb-4">Navigation</h3>
<nav className="space-y-2">
<a href="#" className="block py-2 px-3 rounded hover:bg-gray-200">Dashboard</a>
<a href="#" className="block py-2 px-3 rounded hover:bg-gray-200">Analytics</a>
<a href="#" className="block py-2 px-3 rounded hover:bg-gray-200">Settings</a>
</nav>
</div>
</div>
{/* Main content */}
<div className="flex-1 p-6">
<div className={dashboard.header}>
<h1 className="text-3xl font-bold mb-6">Dashboard</h1>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
{[1, 2, 3, 4, 5, 6].map((index) => (
<div key={index} className={dashboard.widgets[index - 1]}>
<div className="p-6 bg-white rounded-lg shadow">
<h3 className="text-lg font-semibold mb-2">Widget {index}</h3>
<p className="text-gray-600">Widget content</p>
</div>
</div>
))}
</div>
</div>
</div>
)
}
Performance Utilities
useAnimationOptimization
Optimize animations for performance and accessibility.
import { useAnimationOptimization } from '@foundrykit/animation'
function OptimizedAnimation() {
const { shouldAnimate, animationProps } = useAnimationOptimization({
prefersReducedMotion: true,
isLowPowerMode: true,
isMobile: true
})
if (!shouldAnimate) {
return (
<div className="space-y-4">
<h1 className="text-3xl font-bold">Welcome</h1>
<p className="text-lg text-gray-600">Content without animations</p>
<button className="px-4 py-2 bg-blue-600 text-white rounded">
Action Button
</button>
</div>
)
}
return (
<div className="space-y-4">
<div className={animationProps.fadeIn}>
<h1 className="text-3xl font-bold">Welcome</h1>
</div>
<div className={animationProps.slideUp}>
<p className="text-lg text-gray-600">Content with optimized animations</p>
</div>
<div className={animationProps.scale}>
<button className="px-4 py-2 bg-blue-600 text-white rounded">
Action Button
</button>
</div>
</div>
)
}
useAnimationThrottling
Throttle animations to prevent performance issues.
import { useAnimationThrottling } from '@foundrykit/animation'
function ThrottledAnimation() {
const { isThrottled, animationProps } = useAnimationThrottling({
maxAnimations: 3,
throttleDelay: 100
})
const items = ['Item 1', 'Item 2', 'Item 3', 'Item 4', 'Item 5']
return (
<div className="space-y-2">
{items.map((item, index) => (
<div key={index} className={animationProps[index]}>
<div className="p-4 bg-gray-100 rounded">
{item} {isThrottled && '(Throttled)'}
</div>
</div>
))}
</div>
)
}
Advanced Animation Patterns
Conditional Animation Rendering
import { useConditionalAnimation } from '@foundrykit/animation'
function ConditionalAnimation() {
const [showContent, setShowContent] = useState(false)
const [animationType, setAnimationType] = useState('fadeIn')
const animationProps = useConditionalAnimation({
condition: showContent,
animation: animationType,
fallback: 'none'
})
return (
<div className="space-y-4">
<div className="space-x-4">
<button onClick={() => setShowContent(!showContent)}>
{showContent ? 'Hide' : 'Show'} Content
</button>
<select
value={animationType}
onChange={(e) => setAnimationType(e.target.value)}
>
<option value="fadeIn">Fade In</option>
<option value="slideUp">Slide Up</option>
<option value="scale">Scale</option>
</select>
</div>
<div className={animationProps}>
<div className="p-6 bg-green-100 rounded">
<h3 className="text-lg font-semibold mb-2">Conditional Content</h3>
<p>This content animates based on the selected animation type.</p>
</div>
</div>
</div>
)
}
Animation State Management
import { useAnimationState } from '@foundrykit/animation'
function AnimationStateManagement() {
const { state, setState, animationProps } = useAnimationState({
initialState: 'idle',
states: {
idle: { animation: 'none' },
loading: { animation: 'fadeIn', duration: 0.3 },
success: { animation: 'scale', duration: 0.5 },
error: { animation: 'shake', duration: 0.6 }
}
})
return (
<div className="space-y-4">
<div className="space-x-2">
<button onClick={() => setState('loading')}>Loading</button>
<button onClick={() => setState('success')}>Success</button>
<button onClick={() => setState('error')}>Error</button>
<button onClick={() => setState('idle')}>Reset</button>
</div>
<div className={animationProps}>
<div className="p-6 bg-gray-100 rounded">
<h3 className="text-lg font-semibold mb-2">State: {state}</h3>
<p>This content animates based on the current state.</p>
</div>
</div>
</div>
)
}
Animation Debugging
useAnimationDebug
Debug animation performance and timing.
import { useAnimationDebug } from '@foundrykit/animation'
function AnimationDebug() {
const debugInfo = useAnimationDebug({
enabled: process.env.NODE_ENV === 'development',
logPerformance: true,
logTiming: true
})
return (
<div className="space-y-4">
<div className="p-4 bg-blue-100 rounded">
<h3 className="font-semibold mb-2">Animation Debug Info</h3>
<pre className="text-sm">
{JSON.stringify(debugInfo, null, 2)}
</pre>
</div>
<div className="p-6 bg-white rounded-lg shadow">
<h2 className="text-2xl font-bold mb-4">Animated Content</h2>
<p>This content will show debug information in development mode.</p>
</div>
</div>
)
}
Next Steps
- Check out performance guidelines for optimal performance
- Review best practices for effective usage
- Explore the animation components for detailed usage examples