How To Use
Ecosistema completo para organización y gestión de contenido con interfaces espaciales
🎨 How to Use Flash Animations
Complete guide to implementing beautiful animations in your GoGrab Space applications.
🏗️ Architecture Overview
Flash-Animations provides a three-layer animation system combining Angular's native animations with Flash-Persistence for optimal performance and user customization:
┌──────────────────────────────────────────────┐
│ Layer 1: Route Configuration │
│ Each route defines animation in route.data │
│ Example: data: { animation: 'slideLeft' } │
└────────────────┬─────────────────────────────┘
↓
┌──────────────────────────────────────────────┐
│ Layer 2: FlashRouteAnimationService │
│ - Tracks route changes automatically │
│ - Uses Angular @animations API │
│ - Provides current state as signals │
└────────────────┬─────────────────────────────┘
↓
┌──────────────────────────────────────────────┐
│ Layer 3: Flash-Persistence Integration │
│ - Auto-saves user animation preferences │
│ - Can override route animations │
│ - Instant restoration on page reload │
└──────────────────────────────────────────────┘
Why Angular Native Animations?
✅ Browser Caching - Animation definitions cached by Angular compiler
✅ AOT Compilation - Compiled ahead-of-time for instant execution
✅ Zero Dependencies - Uses built-in @angular/animations
✅ GPU Accelerated - Automatic transform/opacity optimization
✅ Lifecycle Integrated - Automatic cleanup and memory management
✅ Performance - Faster than CSS animations or third-party libraries
Priority System:
- User Preference (if
overrideRouteAnimations: truein Flash-Persistence) - Route Configuration (from
route.data.animation) - Default (
'elegant')
📦 Installation
The library is already available in the monorepo. No installation needed!
Import path: @widgets-editor/flash-animations
🚀 Quick Start
1. Basic HTML Directive Usage
The simplest way to add animations to any element:
<!-- Fade in animation on mount -->
<div flashAnim="fade-in" faSpeed="fast">
Content appears with fade effect
</div>
<!-- Slide up with elegant timing -->
<section flashAnim="slide-up" faSpeed="elegant">
Beautiful entrance animation
</section>
2. Interactive Animations
Add animations triggered by user interactions:
<!-- Click animation -->
<button flashAnimClick="bounce-in">
Click me!
</button>
<!-- Hover animation with exit effect -->
<div flashAnimHover="glow" flashAnimExit="fade-out">
Hover to see effect
</div>
<!-- Multiple interactions -->
<button
flashAnimClick="shake"
flashAnimHover="pulse"
flashAnimFocus="scale-in">
Interactive button
</button>
3. Scroll-Triggered Animations
Animate elements when they scroll into view:
<!-- Basic viewport animation -->
<div flashAnimViewport="slide-up" [flashAnimThreshold]="0.5">
Appears when scrolled into view
</div>
<!-- With custom settings -->
<section
flashAnimViewport="fade-in"
[flashAnimThreshold]="0.3"
[faTriggerOnce]="true"
faSpeed="elegant">
Animates once on scroll
</section>
🎭 Available Animation Presets
Entrance Animations
fade-in- Smooth opacity transitionslide-up- Elegant upward slideslide-down- Graceful downward slideslide-left- Smooth leftward motionslide-right- Smooth rightward motionscale-in- Growing scale effectbounce-in- Playful bounce entrance
Exit Animations
fade-out- Smooth fade awayscale-out- Shrinking scale effectbounce-out- Playful bounce exit
Attention Animations
pulse- Rhythmic pulsing effectshake- Attention-getting shakeglow- Illuminating glow effect
Special Animations
glassmorphism-reveal- Beautiful glass effectshimmer-load- Shimmering loading stateliquid-reveal- Fluid morphing animation
⚡ Speed Settings
Control animation timing with speed options:
instant- 100ms (very quick)fast- 300ms (snappy)normal- 600ms (balanced)slow- 1200ms (dramatic)elegant- 800ms (smooth and polished)
<div flashAnim="fade-in" faSpeed="instant">Quick fade</div>
<div flashAnim="slide-up" faSpeed="elegant">Smooth slide</div>
🎯 Directive Reference
FlashAnimateDirective - Basic Animations
Selector: [flashAnim]
<div
[flashAnim]="animationPreset"
[faSpeed]="speed"
[faDelay]="delayMs"
[faDuration]="durationMs"
[faEnabled]="isEnabled"
[faTrigger]="triggerValue">
Content
</div>
Inputs:
flashAnim- Animation preset name (required)faSpeed- Speed setting (optional)faDelay- Delay in milliseconds (optional)faDuration- Duration in milliseconds (optional)faEnabled- Enable/disable animation (optional, default: true)faTrigger- Change this value to re-trigger animation (optional)
FlashAnimateInteractionDirective - User Interactions
Selector: [flashAnimClick], [flashAnimHover], [flashAnimFocus]
<button
flashAnimClick="bounce-in"
flashAnimHover="pulse"
flashAnimFocus="glow"
flashAnimBlur="fade-out"
[faSpeed]="speed"
[faEnabled]="isEnabled">
Interactive element
</button>
Inputs:
flashAnimClick- Animation on click (optional)flashAnimHover- Animation on hover (optional)flashAnimExit- Animation on mouse leave (optional)flashAnimFocus- Animation on focus (optional)flashAnimBlur- Animation on blur (optional)faSpeed- Speed for all animations (optional)faEnabled- Enable/disable (optional, default: true)
FlashAnimateViewportDirective - Scroll Animations
Selector: [flashAnimViewport]
<div
flashAnimViewport="slide-up"
[flashAnimThreshold]="0.5"
[faRootMargin]="'0px'"
[faTriggerOnce]="true"
[faSpeed]="speed"
[faEnabled]="isEnabled"
(faEnter)="onEnterViewport()"
(faExit)="onExitViewport()">
Viewport-aware content
</div>
Inputs:
flashAnimViewport- Animation preset (required)flashAnimThreshold- Intersection threshold 0-1 (optional, default: 0.2)faRootMargin- Root margin for observer (optional, default: '0px')faTriggerOnce- Trigger only once (optional, default: true)faSpeed- Animation speed (optional)faEnabled- Enable/disable (optional, default: true)
Outputs:
faEnter- Emits when element enters viewportfaExit- Emits when element exits viewport
🛣️ Route Animations (Recommended for Page Transitions)
Use Angular's native animations for smooth, cached, GPU-accelerated route transitions.
Complete Implementation
Step 1: App Component Setup
import { Component, OnInit, OnDestroy, signal } from '@angular/core';
import { Router, NavigationEnd } from '@angular/router';
import { filter } from 'rxjs/operators';
import {
flashRouteAnimations,
FlashRouteAnimationService
} from '@widgets-editor/flash-animations';
import { storageKeyResolver } from '@flash-persistence';
@Component({
selector: 'app-root',
standalone: true,
animations: [flashRouteAnimations], // Angular native animations
template: `
<div class="route-container"
[@flashRouteTransition]="getRouteAnimationData()">
<router-outlet></router-outlet>
</div>
`,
styleUrls: ['./app.component.scss']
})
export class AppComponent implements OnInit, OnDestroy {
private animationDataCache = signal<string>('elegant');
private storageUnsubscribe?: () => void;
constructor(
public routeAnimations: FlashRouteAnimationService,
private router: Router
) {}
ngOnInit() {
// Initialize route animation tracking
this.routeAnimations.initialize();
// Update on route changes
this.router.events
.pipe(filter(event => event instanceof NavigationEnd))
.subscribe(() => this.refreshAnimationCache());
// Listen to Flash-Persistence animation preference changes
this.storageUnsubscribe = storageKeyResolver.onStorageChange(
'flash:animation-settings',
() => this.refreshAnimationCache()
);
// Initial cache
this.refreshAnimationCache();
}
getRouteAnimationData() {
return this.animationDataCache();
}
private refreshAnimationCache() {
// Get animation from route config or user preference
const routeAnimation = this.routeAnimations.getCurrentAnimationState();
this.animationDataCache.set(routeAnimation);
}
ngOnDestroy() {
if (this.storageUnsubscribe) {
this.storageUnsubscribe();
}
}
}
Step 2: Add GPU-Accelerated CSS
// app.component.scss
.route-container {
position: relative;
width: 100%;
height: 100%;
display: block;
// GPU acceleration for smooth animations
will-change: transform, opacity;
transform: translateZ(0);
backface-visibility: hidden;
perspective: 1000px;
// Smooth child transitions
> * {
will-change: transform, opacity;
backface-visibility: hidden;
}
}
Step 3: Enable Animations in main.ts
import { provideAnimations } from '@angular/platform-browser/animations';
export const appConfig: ApplicationConfig = {
providers: [
provideAnimations(), // Synchronous loading (NOT provideAnimationsAsync)
// ... other providers
]
};
⚠️ Important: Use provideAnimations(), not provideAnimationsAsync(), to ensure animations load immediately.
Step 4: Configure Route Animations
import { Routes } from '@angular/router';
const routes: Routes = [
{
path: 'dashboard',
component: DashboardComponent,
data: {
animation: 'elegant', // Polished, subtle
animationSpeed: 'normal'
}
},
{
path: 'space-map',
component: SpaceMapComponent,
data: {
animation: 'scale', // Zoom effect
animationSpeed: 'elegant'
}
},
{
path: 'editor',
component: EditorComponent,
data: {
animation: 'slideLeft', // Directional
animationSpeed: 'fast'
}
}
];
Available Route Animations
| Animation | Description | Best For |
|---|---|---|
elegant |
Polished, subtle transition | Main areas, default |
fade |
Simple opacity | Quick changes |
slideUp |
Slide from bottom | Detail views |
slideLeft |
Slide from right | Forward navigation |
slideRight |
Slide from left | Back navigation |
scale |
Zoom effect | Focus transitions |
bounce |
Playful bounce | Fun interactions |
Animation Speeds
| Speed | Duration | Use Case |
|---|---|---|
instant |
100ms | Data updates |
fast |
300ms | Quick transitions |
normal |
600ms | Standard (default) |
slow |
1200ms | Dramatic |
elegant |
800ms | Polished |
Route Transition Flow
User clicks link
↓
Router navigates
↓
FlashRouteAnimationService reads route.data.animation
↓
Service updates currentAnimation signal
↓
App component receives new state
↓
[@flashRouteTransition] trigger fires
↓
:leave animation (200ms) - old view
↓
:enter animation (400ms) - new view
↓
Complete (total ~600ms)
Flash-Persistence Integration
Users can customize route animations in the /flash-persistence demo:
// In flash-animations-demo component:
protected readonly animationSettings = autoFlashState('animation-settings', {
selectedPreset: 'slide-up',
speed: 'fast',
enabled: true,
overrideRouteAnimations: true // User preference takes priority
});
Priority:
- User preference (if
overrideRouteAnimations: true) - Route configuration (from
route.data.animation) - Default (
'elegant')
💻 TypeScript Programmatic Control
Using Helper Functions
Quick and easy animation helpers:
import {
flashAnimate,
flashSuccess,
flashError,
flashPulse,
flashShake,
flashGlow
} from '@widgets-editor/flash-animations';
export class MyComponent {
@ViewChild('element') element!: ElementRef;
async animateElement() {
// Simple animation
await flashAnimate(this.element, 'fade-in', 'fast');
}
showSuccessMessage() {
flashSuccess(this.element, 'Saved successfully!');
}
showError() {
flashError(this.element, 'Something went wrong');
}
drawAttention() {
flashPulse(this.element, 2); // Pulse twice
}
highlightElement() {
flashGlow(this.element, '#22c55e', 800); // Green glow for 800ms
}
}
Using FlashAnimationController
Advanced control with sequences and chains:
import { FlashAnimationController } from '@widgets-editor/flash-animations';
export class MyComponent {
private controller = inject(FlashAnimationController);
@ViewChild('element') element!: ElementRef;
async complexAnimation() {
// Single animation with options
await this.controller.animate(this.element, 'bounce-in', {
speed: 'fast',
delay: 300,
onComplete: () => console.log('Done!')
});
}
async runSequence() {
// Run animations in sequence
await this.controller.sequence(this.element, [
{ preset: 'fade-in', speed: 'fast' },
{ preset: 'glow', duration: 800, delay: 200 },
{ preset: 'pulse', speed: 'normal' }
]);
}
async staggerAnimation() {
// Animate multiple elements with stagger
await this.controller.stagger(
[this.card1, this.card2, this.card3],
'slide-up',
{ speed: 'fast', staggerDelay: 150 }
);
}
}
Animation Chains (Fluent API)
Build complex animation sequences with a fluent API:
import { createAnimationChain } from '@widgets-editor/flash-animations';
export class MyComponent {
@ViewChild('element') element!: ElementRef;
async playAnimationChain() {
const chain = createAnimationChain(this.element)
.fadeIn('fast')
.wait(300)
.pulse(2)
.glow(1000)
.bounceIn('elegant');
await chain.play();
}
}
🎨 Advanced Examples
Example 1: Animated Card Grid
<div class="card-grid">
@for (card of cards; track card.id; let i = $index) {
<div
class="card"
flashAnimViewport="slide-up"
[flashAnimThreshold]="0.3"
[faDelay]="i * 100"
faSpeed="elegant">
<h3>{{ card.title }}</h3>
<p>{{ card.description }}</p>
<button flashAnimClick="bounce-in" flashAnimHover="pulse">
Action
</button>
</div>
}
</div>
Example 2: Form Validation Feedback
export class FormComponent {
@ViewChild('emailInput') emailInput!: ElementRef;
async validateEmail() {
if (this.email.invalid) {
await flashShake(this.emailInput);
await flashError(this.emailInput);
} else {
await flashSuccess(this.emailInput);
}
}
}
<input
#emailInput
type="email"
[(ngModel)]="email"
(blur)="validateEmail()">
Example 3: Loading States
export class DataComponent {
@ViewChild('container') container!: ElementRef;
async loadData() {
const stopLoading = flashStartLoading(this.container, 'Loading...');
try {
await this.dataService.fetchData();
flashSuccess(this.container);
} catch (error) {
flashError(this.container);
} finally {
stopLoading();
}
}
}
Example 4: State Change Animations
export class CounterComponent {
count = signal(0);
@ViewChild('display') display!: ElementRef;
async increment() {
this.count.update(c => c + 1);
await flashPulse(this.display);
}
}
<div #display [flashAnim]="'pulse'" [faTrigger]="count()">
Count: {{ count() }}
</div>
♿ Accessibility
Flash Animations automatically respects user preferences:
Prefers Reduced Motion
The library automatically detects prefers-reduced-motion and:
- Reduces animation durations by 50%
- Simplifies complex animations to simple fades
- Ensures maximum duration of 300ms
Keyboard Navigation
All interactive directives support keyboard navigation:
- Focus animations work with Tab key
- Click animations work with Enter/Space
- Proper
tabindexadded automatically
Screen Readers
Animations don't interfere with screen readers and maintain semantic HTML structure.
🔧 Configuration & Customization
Component-Level Setup
import {
FlashAnimateDirective,
FlashAnimateInteractionDirective,
FlashAnimateViewportDirective
} from '@widgets-editor/flash-animations';
@Component({
standalone: true,
imports: [
FlashAnimateDirective,
FlashAnimateInteractionDirective,
FlashAnimateViewportDirective
]
})
export class MyComponent {}
Import Types
import {
FlashAnimationPreset,
FlashAnimationSpeed,
FlashAnimationOptions
} from '@widgets-editor/flash-animations';
🎯 Best Practices
1. Use Appropriate Animations
- Entrance:
fade-in,slide-up,scale-in - Exit:
fade-out,scale-out - Attention:
pulse,shake,glow - Success:
bounce-in+glow - Error:
shake+ red glow
2. Choose Right Speed
- Instant: Loading indicators, state changes
- Fast: Click feedback, hover effects
- Normal: General transitions
- Elegant: Important content reveals
- Slow: Dramatic effects, hero sections
3. Respect User Preferences
- Library handles
prefers-reduced-motionautomatically - Test with reduced motion enabled
- Don't force animations on essential UI
4. Performance Tips
- Use viewport animations for off-screen content
- Limit simultaneous animations
- Prefer
transformandopacity(GPU accelerated) - Use
faTriggerOncefor scroll animations
5. Accessibility
- Ensure animations don't hide important information
- Provide keyboard alternatives for hover effects
- Test with screen readers
- Don't rely solely on animation to convey meaning
🐛 Troubleshooting
Animations Not Working?
Check imports:
imports: [FlashAnimateDirective, ...]Rebuild library:
yarn nx build flash-animationsRestart dev server:
nx serve your-app
Type Errors?
Ensure you import types:
import { FlashAnimationPreset } from '@widgets-editor/flash-animations';
Route Animations Not Triggering?
Make sure FlashRouteAnimationService is initialized:
ngOnInit() {
this.routeAnimations.initialize();
}
📚 Additional Resources
- Flash Animations Overview - Complete feature documentation
- Animation Presets - Full preset reference
- Examples - Real-world usage examples
- API Reference - Complete API documentation
🎉 Summary
Flash Animations provides three simple ways to add animations:
- HTML Directives -
flashAnim,flashAnimClick,flashAnimViewport - Helper Functions -
flashAnimate(),flashSuccess(), etc. - Route Animations -
flashRouteAnimationsservice
Choose the method that best fits your use case and enjoy beautiful, performant animations throughout your application!
🌠 Happy Animating!