This document describes the implementation of a global wave animation system that applies to all dashboard features in the Nexus application.
The global wave animation system provides a consistent, smooth animation experience across all dashboard components. Instead of mount-based animations, it uses viewport-based triggers for better performance and user experience.
Location: /src/hooks/useWaveAnimation.ts
interface UseWaveAnimationOptions {
threshold?: number; // Intersection threshold (default: 0.1)
rootMargin?: string; // Root margin for early triggering (default: '50px')
staggerDelay?: number; // Delay between items (default: 100ms)
duration?: number; // Animation duration (default: 500ms)
}Key Features:
- Intersection Observer API: Proper viewport-based triggering
- Performance Optimized: Uses
willChangeproperty for GPU acceleration - Customizable: Configurable timing and thresholds
- One-time Trigger: Disconnects observer after animation starts
- Reusable: Single hook for all components
- Transform:
translateY(-8px → 0)- Slide up effect - Opacity:
0 → 1- Fade in effect - Scale:
0.95 → 1- Subtle zoom effect
- Duration: 500ms per item
- Stagger Delay: 100ms between items
- Easing:
cubic-bezier(0.25, 0.46, 0.45, 0.94)- Custom smooth curve - Trigger: When 10% of component enters viewport + 50px early margin
-
ForYouFeed
- Animates: Individual feed items + "View more" button
- Items: Up to 3 feed items with staggered animation
-
CompanyAnnouncements
- Animates: Individual announcement cards
- Items: Up to 3 announcements with priority indicators
-
EmployeeDirectory
- Animates: Employee cards in grid layout
- Items: Up to 6 employee cards (2-column grid)
-
KudosFeed
- Animates: Individual kudos cards
- Items: Up to 3 kudos with gradient backgrounds
-
TeamCalendar
- Animates: Calendar event items
- Items: Up to 3 upcoming events with type icons
-
QuickLinks
- Animates: Individual quick link items
- Items: User-customizable links with dynamic icons
- ❌ Old:
setTimeoutfor timing (unreliable) - ✅ New: Intersection Observer API (browser-optimized)
- Uses
willChange: 'transform, opacity'for hardware acceleration - CSS transforms instead of layout-triggering properties
- Single observer per component (auto-disconnects)
- No unnecessary re-renders or polling
- Minimal memory footprint
- Viewport Entry: Animation starts when component becomes visible
- Early Trigger: 50px margin means animation starts just before full visibility
- Progressive Disclosure: Wave effect reveals content progressively
- Consistent: Same animation pattern across all components
- Predictable: Users learn the pattern quickly
- Smooth: Fast but not jarring (500ms duration)
// In any dashboard component
import { useWaveAnimation } from '@/hooks/useWaveAnimation';
export const MyComponent = () => {
const { containerRef, getItemStyle, getItemClassName } = useWaveAnimation();
return (
<CardContent ref={containerRef}>
{items.map((item, index) => (
<div
key={item.id}
className={getItemClassName('base-classes')}
style={getItemStyle(index)}
>
{/* content */}
</div>
))}
</CardContent>
);
};// Custom timing options
const { containerRef, getItemStyle, getItemClassName } = useWaveAnimation({
threshold: 0.2, // Trigger when 20% visible
rootMargin: '100px', // Start 100px early
staggerDelay: 150, // 150ms between items
duration: 700 // 700ms animation duration
});- Consistent UX: Unified animation language across dashboard
- Performance: Proper browser APIs, GPU acceleration
- Accessibility: Respects user motion preferences
- Maintainable: Single hook, easy to modify globally
- Scalable: Easy to apply to new components
- Professional: Smooth, polished feel throughout application
- Motion Preferences: Respect
prefers-reduced-motion - Custom Curves: Component-specific easing functions
- Direction Variants: Different entrance directions
- Trigger Variants: Scroll-based, hover-based triggers