feat: add animated components for enhanced UI/UX
- Introduced DrawLine component for drawing animations. - Added LazyRevealImage component for lazy loading images with reveal animations. - Implemented TextDiffuseReveal for animated text reveals with staggered effects. - Created TopProgressBar for a dynamic loading indicator. - Added PointCloud mock for testing animations. - Developed useReducedMotion hook to handle user preferences for reduced motion. - Centralized animation configurations in config.ts for easier management. - Defined animation variants in variants.ts for consistent animation effects. - Established AnimationProvider to supply global animation settings. - Created tests for AnimationProvider and useReducedMotion hook. - Added SVG assets for branding and UI elements. - Documented frontend review plan and hero circuit board animation plan.
This commit is contained in:
1 parent
0ab6930f92
commit
08dd046887
76 files changed
+21682
-1197
No files matched your search
@@ -0,0 +1 @@
|
||||
{"specId": "3fcf2565-1720-4d06-9224-82b23b02204c", "workflowType": "requirements-first", "specType": "feature"}
|
||||
@@ -0,0 +1,534 @@
|
||||
# Design Document: Premium Animations
|
||||
|
||||
## Overview
|
||||
|
||||
Este documento detalha o design técnico para implementar animações premium no portfolio evandro.dev.br, inspiradas no estilo suave e elegante do site on.energy. O sistema de animações será construído sobre Framer Motion e Lenis, mantendo a identidade visual existente (cores, tipografia Monument Extended, paleta --slash #ccff00) enquanto adiciona transições fluidas, scroll-triggered animations, parallax sutil e animações de hover sofisticadas.
|
||||
|
||||
### Objetivos Principais
|
||||
|
||||
1. Elevar a experiência visual com animações premium e fluidas
|
||||
2. Manter performance consistente (60fps) em todos os dispositivos
|
||||
3. Garantir acessibilidade completa com suporte a prefers-reduced-motion
|
||||
4. Criar um sistema de animações reutilizável e escalável
|
||||
5. Integrar smooth scroll global com Lenis
|
||||
6. Implementar interações sofisticadas (magnetic buttons, custom cursor)
|
||||
|
||||
### Princípios de Design
|
||||
|
||||
- **Performance First**: Usar apenas propriedades GPU-accelerated (transform, opacity)
|
||||
- **Accessibility First**: Respeitar prefers-reduced-motion em todas as animações
|
||||
- **Progressive Enhancement**: Funcionalidade básica sem JavaScript, animações como enhancement
|
||||
- **Consistency**: Usar curvas de easing e durações consistentes em todo o sistema
|
||||
- **Subtlety**: Animações devem ser elegantes e discretas, não distrativas
|
||||
|
||||
## Architecture
|
||||
|
||||
### System Overview
|
||||
|
||||
O sistema de animações será organizado em camadas modulares:
|
||||
|
||||
```
|
||||
Animation System
|
||||
├── Core Layer (Hooks & Utilities)
|
||||
│ ├── useScrollTrigger - Detecta elementos no viewport
|
||||
│ ├── useParallax - Aplica efeitos parallax
|
||||
│ ├── useReducedMotion - Detecta preferências de acessibilidade
|
||||
│ ├── useMagneticEffect - Implementa efeito magnético
|
||||
│ └── animationConfig - Configurações centralizadas
|
||||
│
|
||||
├── Component Layer (Wrappers Reutilizáveis)
|
||||
│ ├── ScrollReveal - Wrapper para scroll-triggered animations
|
||||
│ ├── StaggerContainer - Container para stagger animations
|
||||
│ ├── ParallaxElement - Wrapper para parallax effects
|
||||
│ ├── PageTransition - Transições entre páginas
|
||||
│ ├── ImageReveal - Reveal animado para imagens
|
||||
│ ├── TextReveal - Reveal animado para textos
|
||||
│ └── CustomCursor - Cursor customizado
|
||||
│
|
||||
├── Integration Layer (Providers & Context)
|
||||
│ ├── LenisProvider - Smooth scroll global
|
||||
│ ├── AnimationProvider - Context para configurações
|
||||
│ └── CursorProvider - Context para cursor customizado
|
||||
│
|
||||
└── Enhancement Layer (Micro-interactions)
|
||||
├── Card hover effects
|
||||
├── Button hover effects
|
||||
├── Form field interactions
|
||||
└── Loading states
|
||||
```
|
||||
|
||||
### Technology Stack
|
||||
|
||||
- **Framer Motion 12.23.12**: Biblioteca principal de animações
|
||||
- **Lenis 1.3.18**: Smooth scroll library
|
||||
- **React 19.1.0**: Framework base
|
||||
- **Next.js 15.5.9**: App Router para routing
|
||||
- **TypeScript**: Type safety
|
||||
- **Tailwind CSS 4**: Styling utilities
|
||||
|
||||
### Integration Points
|
||||
|
||||
1. **App Layout**: LenisProvider e AnimationProvider no root layout
|
||||
2. **Page Components**: PageTransition wrapper em cada página
|
||||
3. **Section Components**: ScrollReveal wrapper em seções principais
|
||||
4. **Card Components**: Hover effects e stagger animations
|
||||
5. **Form Components**: Micro-interactions em campos
|
||||
6. **Hero Component**: Remoção da fase logo, manutenção de typing animation
|
||||
|
||||
## Components and Interfaces
|
||||
|
||||
### Core Hooks
|
||||
|
||||
#### useScrollTrigger
|
||||
|
||||
Hook para detectar quando elementos entram no viewport e disparar animações.
|
||||
|
||||
```typescript
|
||||
interface UseScrollTriggerOptions {
|
||||
threshold?: number; // Porcentagem do elemento visível (default: 0.2)
|
||||
once?: boolean; // Executar apenas uma vez (default: true)
|
||||
margin?: string; // Margin do viewport (default: "0px")
|
||||
}
|
||||
|
||||
interface UseScrollTriggerReturn {
|
||||
ref: RefObject<HTMLElement>;
|
||||
isInView: boolean;
|
||||
entry: IntersectionObserverEntry | null;
|
||||
}
|
||||
|
||||
function useScrollTrigger(options?: UseScrollTriggerOptions): UseScrollTriggerReturn
|
||||
```
|
||||
|
||||
**Implementação**: Wrapper sobre `useInView` do Framer Motion com configurações otimizadas.
|
||||
|
||||
#### useParallax
|
||||
|
||||
Hook para aplicar efeitos parallax em elementos durante o scroll.
|
||||
|
||||
```typescript
|
||||
interface UseParallaxOptions {
|
||||
speed?: number; // Velocidade do parallax (default: 0.5 = 50% mais lento)
|
||||
direction?: "vertical" | "horizontal"; // Direção do movimento (default: "vertical")
|
||||
disabled?: boolean; // Desabilitar parallax (usado com reduced motion)
|
||||
}
|
||||
|
||||
interface UseParallaxReturn {
|
||||
ref: RefObject<HTMLElement>;
|
||||
style: MotionStyle;
|
||||
}
|
||||
|
||||
function useParallax(options?: UseParallaxOptions): UseParallaxReturn
|
||||
```
|
||||
|
||||
**Implementação**: Usa `useScroll` e `useTransform` do Framer Motion para calcular posição baseada no scroll.
|
||||
|
||||
#### useReducedMotion
|
||||
|
||||
Hook para detectar preferência de movimento reduzido do usuário.
|
||||
|
||||
```typescript
|
||||
function useReducedMotion(): boolean
|
||||
```
|
||||
|
||||
**Implementação**: Wrapper sobre `useReducedMotion` do Framer Motion, retorna `true` se `prefers-reduced-motion: reduce` está ativo.
|
||||
|
||||
#### useMagneticEffect
|
||||
|
||||
Hook para implementar efeito magnético em botões.
|
||||
|
||||
```typescript
|
||||
interface UseMagneticEffectOptions {
|
||||
radius?: number; // Raio de influência em pixels (default: 80)
|
||||
strength?: number; // Força do efeito, max movement em pixels (default: 12)
|
||||
disabled?: boolean; // Desabilitar efeito (usado com reduced motion)
|
||||
}
|
||||
|
||||
interface UseMagneticEffectReturn {
|
||||
ref: RefObject<HTMLElement>;
|
||||
style: MotionStyle;
|
||||
}
|
||||
|
||||
function useMagneticEffect(options?: UseMagneticEffectOptions): UseMagneticEffectReturn
|
||||
```
|
||||
|
||||
**Implementação**: Rastreia posição do mouse, calcula distância ao elemento, aplica transform proporcional com spring physics.
|
||||
|
||||
### Component Wrappers
|
||||
|
||||
#### ScrollReveal
|
||||
|
||||
Componente wrapper para aplicar scroll-triggered animations.
|
||||
|
||||
```typescript
|
||||
interface ScrollRevealProps {
|
||||
children: React.ReactNode;
|
||||
direction?: "up" | "down" | "left" | "right"; // Direção do slide (default: "up")
|
||||
distance?: number; // Distância do movimento em pixels (default: 24)
|
||||
duration?: number; // Duração da animação em segundos (default: 0.6)
|
||||
delay?: number; // Delay antes da animação (default: 0)
|
||||
threshold?: number; // Threshold do viewport (default: 0.2)
|
||||
once?: boolean; // Executar apenas uma vez (default: true)
|
||||
className?: string;
|
||||
}
|
||||
|
||||
function ScrollReveal(props: ScrollRevealProps): JSX.Element
|
||||
```
|
||||
|
||||
**Comportamento**:
|
||||
- Normal: fade in + slide na direção especificada com blur inicial
|
||||
- Reduced Motion: apenas fade in simples, sem movimento ou blur
|
||||
|
||||
#### StaggerContainer
|
||||
|
||||
Container para aplicar stagger animations em elementos filhos.
|
||||
|
||||
```typescript
|
||||
interface StaggerContainerProps {
|
||||
children: React.ReactNode;
|
||||
staggerDelay?: number; // Delay entre elementos em segundos (default: 0.08)
|
||||
initialDelay?: number; // Delay inicial antes do primeiro elemento (default: 0)
|
||||
className?: string;
|
||||
}
|
||||
|
||||
function StaggerContainer(props: StaggerContainerProps): JSX.Element
|
||||
```
|
||||
|
||||
**Implementação**: Usa `motion.div` com `variants` para aplicar stagger automático aos filhos.
|
||||
|
||||
#### ParallaxElement
|
||||
|
||||
Wrapper para aplicar parallax effect em elementos.
|
||||
|
||||
```typescript
|
||||
interface ParallaxElementProps {
|
||||
children: React.ReactNode;
|
||||
speed?: number; // Velocidade do parallax (default: 0.5)
|
||||
direction?: "vertical" | "horizontal";
|
||||
className?: string;
|
||||
}
|
||||
|
||||
function ParallaxElement(props: ParallaxElementProps): JSX.Element
|
||||
```
|
||||
|
||||
**Comportamento**:
|
||||
- Normal: movimento parallax suave
|
||||
- Reduced Motion: sem movimento, elemento estático
|
||||
|
||||
#### PageTransition
|
||||
|
||||
Wrapper para transições entre páginas.
|
||||
|
||||
```typescript
|
||||
interface PageTransitionProps {
|
||||
children: React.ReactNode;
|
||||
}
|
||||
|
||||
function PageTransition(props: PageTransitionProps): JSX.Element
|
||||
```
|
||||
|
||||
**Comportamento**:
|
||||
- Normal: fade in de 0.4s com ease-out
|
||||
- Reduced Motion: fade in de 0.15s
|
||||
|
||||
#### ImageReveal
|
||||
|
||||
Componente para reveal animado de imagens.
|
||||
|
||||
```typescript
|
||||
interface ImageRevealProps {
|
||||
src: string;
|
||||
alt: string;
|
||||
width?: number;
|
||||
height?: number;
|
||||
className?: string;
|
||||
priority?: boolean;
|
||||
}
|
||||
|
||||
function ImageReveal(props: ImageRevealProps): JSX.Element
|
||||
```
|
||||
|
||||
**Comportamento**:
|
||||
- Normal: clip-path reveal + fade in + scale (0.98 → 1) + blur (8px → 0px), duração 0.9s
|
||||
- Reduced Motion: apenas fade in simples
|
||||
|
||||
#### TextReveal
|
||||
|
||||
Componente para reveal animado de textos por palavra.
|
||||
|
||||
```typescript
|
||||
interface TextRevealProps {
|
||||
text: string;
|
||||
as?: "h1" | "h2" | "h3" | "h4" | "h5" | "h6" | "p" | "span"; // Tag HTML (default: "p")
|
||||
staggerDelay?: number; // Delay entre palavras (default: 0.04)
|
||||
className?: string;
|
||||
}
|
||||
|
||||
function TextReveal(props: TextRevealProps): JSX.Element
|
||||
```
|
||||
|
||||
**Comportamento**:
|
||||
- Normal: cada palavra com blur (6px → 0px) + scale (0.95 → 1) + clip-path slide horizontal
|
||||
- Reduced Motion: texto completo com fade in simples
|
||||
|
||||
#### CustomCursor
|
||||
|
||||
Componente para cursor customizado.
|
||||
|
||||
```typescript
|
||||
interface CustomCursorProps {
|
||||
size?: number; // Tamanho base do cursor (default: 40)
|
||||
expandedSize?: number; // Tamanho expandido (default: 60)
|
||||
color?: string; // Cor do cursor (default: "var(--slash)")
|
||||
}
|
||||
|
||||
function CustomCursor(props: CustomCursorProps): JSX.Element
|
||||
```
|
||||
|
||||
**Comportamento**:
|
||||
- Desktop: cursor customizado com smooth delay, expande sobre interativos
|
||||
- Touch devices: cursor padrão do sistema
|
||||
- Reduced Motion: cursor padrão do sistema
|
||||
|
||||
### Providers
|
||||
|
||||
#### LenisProvider
|
||||
|
||||
Provider para smooth scroll global.
|
||||
|
||||
```typescript
|
||||
interface LenisProviderProps {
|
||||
children: React.ReactNode;
|
||||
options?: {
|
||||
duration?: number; // Duração do smooth scroll (default: 1.2)
|
||||
easing?: number[]; // Curva de easing (default: [0.25, 0.0, 0.35, 1.0])
|
||||
smoothWheel?: boolean; // Smooth wheel scroll (default: true)
|
||||
smoothTouch?: boolean; // Smooth touch scroll (default: false)
|
||||
};
|
||||
}
|
||||
|
||||
function LenisProvider(props: LenisProviderProps): JSX.Element
|
||||
```
|
||||
|
||||
**Implementação**: Inicializa Lenis, sincroniza com RAF, fornece instância via context.
|
||||
|
||||
#### AnimationProvider
|
||||
|
||||
Provider para configurações globais de animação.
|
||||
|
||||
```typescript
|
||||
interface AnimationConfig {
|
||||
reducedMotion: boolean;
|
||||
easings: {
|
||||
easeOut: string;
|
||||
easeIn: string;
|
||||
spring: { stiffness: number; damping: number };
|
||||
};
|
||||
durations: {
|
||||
fast: number;
|
||||
normal: number;
|
||||
slow: number;
|
||||
};
|
||||
}
|
||||
|
||||
interface AnimationProviderProps {
|
||||
children: React.ReactNode;
|
||||
}
|
||||
|
||||
function AnimationProvider(props: AnimationProviderProps): JSX.Element
|
||||
function useAnimationConfig(): AnimationConfig
|
||||
```
|
||||
|
||||
**Implementação**: Detecta reduced motion, fornece configurações centralizadas via context.
|
||||
|
||||
#### CursorProvider
|
||||
|
||||
Provider para cursor customizado.
|
||||
|
||||
```typescript
|
||||
interface CursorProviderProps {
|
||||
children: React.ReactNode;
|
||||
}
|
||||
|
||||
function CursorProvider(props: CursorProviderProps): JSX.Element
|
||||
function useCursor(): {
|
||||
setExpanded: (expanded: boolean) => void;
|
||||
setColor: (color: string) => void;
|
||||
}
|
||||
```
|
||||
|
||||
**Implementação**: Gerencia estado do cursor, fornece métodos para controle via context.
|
||||
|
||||
## Data Models
|
||||
|
||||
### Animation Configuration
|
||||
|
||||
Configurações centralizadas para todas as animações.
|
||||
|
||||
```typescript
|
||||
export const animationConfig = {
|
||||
// Easing curves
|
||||
easings: {
|
||||
easeOut: "cubic-bezier(0.16, 1, 0.3, 1)",
|
||||
easeIn: "cubic-bezier(0.4, 0, 1, 1)",
|
||||
spring: {
|
||||
default: { stiffness: 200, damping: 20 },
|
||||
hover: { stiffness: 260, damping: 20 },
|
||||
magnetic: { stiffness: 150, damping: 15 },
|
||||
gentle: { stiffness: 60, damping: 20 },
|
||||
},
|
||||
},
|
||||
|
||||
// Durations (in seconds)
|
||||
durations: {
|
||||
instant: 0.15,
|
||||
fast: 0.3,
|
||||
normal: 0.6,
|
||||
slow: 0.9,
|
||||
verySlow: 1.2,
|
||||
},
|
||||
|
||||
// Scroll trigger
|
||||
scrollTrigger: {
|
||||
threshold: 0.2,
|
||||
once: true,
|
||||
margin: "0px",
|
||||
},
|
||||
|
||||
// Stagger
|
||||
stagger: {
|
||||
default: 0.08,
|
||||
fast: 0.04,
|
||||
slow: 0.12,
|
||||
reducedMotion: 0.03,
|
||||
},
|
||||
|
||||
// Parallax
|
||||
parallax: {
|
||||
speed: 0.5, // 50% mais lento que scroll normal
|
||||
maxDistance: 100, // pixels
|
||||
},
|
||||
|
||||
// Magnetic effect
|
||||
magnetic: {
|
||||
radius: 80, // pixels
|
||||
strength: 12, // max movement in pixels
|
||||
},
|
||||
|
||||
// Cursor
|
||||
cursor: {
|
||||
size: 40,
|
||||
expandedSize: 60,
|
||||
followDelay: 0.1,
|
||||
},
|
||||
|
||||
// Reduced motion overrides
|
||||
reducedMotion: {
|
||||
duration: 0.15,
|
||||
stagger: 0.03,
|
||||
disableParallax: true,
|
||||
disableMagnetic: true,
|
||||
disableCursor: true,
|
||||
},
|
||||
} as const;
|
||||
```
|
||||
|
||||
### Variant Presets
|
||||
|
||||
Presets de variants do Framer Motion para animações comuns.
|
||||
|
||||
```typescript
|
||||
export const variants = {
|
||||
// Fade in
|
||||
fadeIn: {
|
||||
initial: { opacity: 0 },
|
||||
animate: { opacity: 1 },
|
||||
exit: { opacity: 0 },
|
||||
},
|
||||
|
||||
// Fade in + slide up
|
||||
fadeInUp: {
|
||||
initial: { opacity: 0, y: 24, filter: "blur(8px)" },
|
||||
animate: { opacity: 1, y: 0, filter: "blur(0px)" },
|
||||
exit: { opacity: 0, y: -24, filter: "blur(8px)" },
|
||||
},
|
||||
|
||||
// Fade in + slide down
|
||||
fadeInDown: {
|
||||
initial: { opacity: 0, y: -24, filter: "blur(8px)" },
|
||||
animate: { opacity: 1, y: 0, filter: "blur(0px)" },
|
||||
exit: { opacity: 0, y: 24, filter: "blur(8px)" },
|
||||
},
|
||||
|
||||
// Fade in + slide left
|
||||
fadeInLeft: {
|
||||
initial: { opacity: 0, x: 24, filter: "blur(8px)" },
|
||||
animate: { opacity: 1, x: 0, filter: "blur(0px)" },
|
||||
exit: { opacity: 0, x: -24, filter: "blur(8px)" },
|
||||
},
|
||||
|
||||
// Fade in + slide right
|
||||
fadeInRight: {
|
||||
initial: { opacity: 0, x: -24, filter: "blur(8px)" },
|
||||
animate: { opacity: 1, x: 0, filter: "blur(0px)" },
|
||||
exit: { opacity: 0, x: 24, filter: "blur(8px)" },
|
||||
},
|
||||
|
||||
// Scale in
|
||||
scaleIn: {
|
||||
initial: { opacity: 0, scale: 0.95 },
|
||||
animate: { opacity: 1, scale: 1 },
|
||||
exit: { opacity: 0, scale: 0.95 },
|
||||
},
|
||||
|
||||
// Image reveal
|
||||
imageReveal: {
|
||||
initial: {
|
||||
opacity: 0,
|
||||
scale: 0.98,
|
||||
filter: "blur(8px)",
|
||||
clipPath: "inset(0 100% 0 0)",
|
||||
},
|
||||
animate: {
|
||||
opacity: 1,
|
||||
scale: 1,
|
||||
filter: "blur(0px)",
|
||||
clipPath: "inset(0 0% 0 0)",
|
||||
},
|
||||
},
|
||||
|
||||
// Text reveal (per word)
|
||||
textReveal: {
|
||||
initial: {
|
||||
opacity: 0,
|
||||
scale: 0.95,
|
||||
filter: "blur(6px)",
|
||||
clipPath: "inset(0 100% 0 0)",
|
||||
},
|
||||
animate: {
|
||||
opacity: 1,
|
||||
scale: 1,
|
||||
filter: "blur(0px)",
|
||||
clipPath: "inset(0 0% 0 0)",
|
||||
},
|
||||
},
|
||||
|
||||
// Stagger container
|
||||
staggerContainer: {
|
||||
animate: {
|
||||
transition: {
|
||||
staggerChildren: 0.08,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
// Reduced motion variants
|
||||
reducedMotion: {
|
||||
fadeIn: {
|
||||
initial: { opacity: 0 },
|
||||
animate: { opacity: 1 },
|
||||
exit: { opacity: 0 },
|
||||
},
|
||||
},
|
||||
} as const;
|
||||
```
|
||||
|
||||
@@ -0,0 +1,218 @@
|
||||
# Requirements Document
|
||||
|
||||
## Introduction
|
||||
|
||||
Este documento define os requisitos para adicionar animações premium ao portfolio evandro.dev.br, inspiradas no estilo suave e elegante do site on.energy. O objetivo é elevar a experiência visual mantendo a identidade atual (cores, tipografia Monument Extended, paleta --slash #ccff00) e adicionando transições fluidas, scroll-triggered animations, parallax sutil e animações de hover sofisticadas.
|
||||
|
||||
## Glossary
|
||||
|
||||
- **Animation_System**: Sistema responsável por gerenciar e executar todas as animações do portfolio
|
||||
- **Hero_Component**: Componente principal da página inicial que exibe o nome e informações do desenvolvedor
|
||||
- **Scroll_Trigger**: Mecanismo que detecta quando elementos entram no viewport para iniciar animações
|
||||
- **Parallax_Effect**: Efeito visual onde elementos se movem em velocidades diferentes durante o scroll
|
||||
- **Stagger_Animation**: Animação sequencial onde elementos aparecem um após o outro com delay
|
||||
- **Reduced_Motion**: Preferência do usuário para reduzir ou desabilitar animações (acessibilidade)
|
||||
- **Design_System**: Conjunto de componentes e estilos reutilizáveis (ds-card, ds-section, etc)
|
||||
- **Viewport**: Área visível da página no navegador do usuário
|
||||
- **Ease_Curve**: Função matemática que define a aceleração/desaceleração de uma animação
|
||||
|
||||
## Requirements
|
||||
|
||||
### Requirement 1: Remover Animação de Logo do Hero
|
||||
|
||||
**User Story:** Como usuário, quero ver apenas o texto "evandro.dev.br" no Hero sem alternância com logo, para ter uma experiência mais direta e focada.
|
||||
|
||||
#### Acceptance Criteria
|
||||
|
||||
1. THE Hero_Component SHALL exibir apenas o texto "evandro.dev.br" sem alternar com a logo
|
||||
2. THE Hero_Component SHALL remover a fase "logo" do ciclo de animação
|
||||
3. THE Hero_Component SHALL manter a animação de digitação (typing) do texto
|
||||
4. THE Hero_Component SHALL manter todas as outras funcionalidades existentes (botões, links sociais, status)
|
||||
5. WHEN a página carrega, THE Hero_Component SHALL iniciar diretamente com a animação de digitação
|
||||
|
||||
### Requirement 2: Implementar Scroll-Triggered Animations
|
||||
|
||||
**User Story:** Como usuário, quero ver elementos aparecerem suavemente conforme faço scroll, para ter uma experiência visual mais envolvente e premium.
|
||||
|
||||
#### Acceptance Criteria
|
||||
|
||||
1. WHEN um elemento entra no Viewport, THE Animation_System SHALL iniciar uma animação de fade in + slide up
|
||||
2. THE Animation_System SHALL usar uma curva de ease-out suave (cubic-bezier(0.16, 1, 0.3, 1))
|
||||
3. THE Animation_System SHALL aplicar scroll-triggered animations em seções (About, Skills, Experience, Projects, WorkModalities, Contact)
|
||||
4. THE Animation_System SHALL aplicar scroll-triggered animations em cards dentro das seções
|
||||
5. THE Animation_System SHALL detectar elementos quando 20% deles estiverem visíveis no Viewport
|
||||
6. THE Animation_System SHALL executar cada animação apenas uma vez (once: true)
|
||||
7. IF Reduced_Motion está ativo, THEN THE Animation_System SHALL usar apenas fade simples sem movimento
|
||||
|
||||
### Requirement 3: Implementar Stagger Animations
|
||||
|
||||
**User Story:** Como usuário, quero ver elementos de uma lista aparecerem sequencialmente, para ter uma sensação de fluidez e ritmo visual.
|
||||
|
||||
#### Acceptance Criteria
|
||||
|
||||
1. WHEN múltiplos cards aparecem em uma seção, THE Animation_System SHALL aplicar stagger delays entre eles
|
||||
2. THE Animation_System SHALL usar delay de 0.08s entre elementos consecutivos
|
||||
3. THE Animation_System SHALL aplicar stagger em grids de cards (Projects, Skills, Experience)
|
||||
4. THE Animation_System SHALL aplicar stagger em listas de tags e métricas
|
||||
5. IF Reduced_Motion está ativo, THEN THE Animation_System SHALL reduzir o delay para 0.03s
|
||||
|
||||
### Requirement 4: Implementar Parallax Sutil em Backgrounds
|
||||
|
||||
**User Story:** Como usuário, quero ver backgrounds com movimento parallax discreto durante o scroll, para adicionar profundidade visual sem distração.
|
||||
|
||||
#### Acceptance Criteria
|
||||
|
||||
1. WHEN o usuário faz scroll, THE Animation_System SHALL aplicar Parallax_Effect em backgrounds decorativos
|
||||
2. THE Parallax_Effect SHALL mover elementos em velocidade 30% mais lenta que o scroll normal
|
||||
3. THE Animation_System SHALL aplicar parallax no grid de fundo do Hero
|
||||
4. THE Animation_System SHALL aplicar parallax no gradiente radial do Hero
|
||||
5. THE Parallax_Effect SHALL ser sutil e não interferir na legibilidade do conteúdo
|
||||
6. IF Reduced_Motion está ativo, THEN THE Animation_System SHALL desabilitar completamente o Parallax_Effect
|
||||
|
||||
### Requirement 5: Implementar Animações de Hover Sofisticadas
|
||||
|
||||
**User Story:** Como usuário, quero ver animações suaves e elegantes ao passar o mouse sobre elementos interativos, para ter feedback visual premium.
|
||||
|
||||
#### Acceptance Criteria
|
||||
|
||||
1. WHEN o usuário passa o mouse sobre um card, THE Animation_System SHALL aplicar lift effect (translateY: -6px)
|
||||
2. WHEN o usuário passa o mouse sobre um card, THE Animation_System SHALL aumentar a sombra suavemente
|
||||
3. WHEN o usuário passa o mouse sobre botões, THE Animation_System SHALL aplicar scale de 1.03
|
||||
4. WHEN o usuário passa o mouse sobre links sociais, THE Animation_System SHALL aplicar rotação sutil (-3deg a 3deg)
|
||||
5. THE Animation_System SHALL usar spring physics para animações de hover (stiffness: 200, damping: 20)
|
||||
6. THE Animation_System SHALL adicionar glow effect sutil em elementos com cor --slash ao hover
|
||||
7. IF Reduced_Motion está ativo, THEN THE Animation_System SHALL usar apenas mudanças de opacidade
|
||||
|
||||
### Requirement 6: Implementar Transições de Página Suaves
|
||||
|
||||
**User Story:** Como desenvolvedor, quero ter um sistema de transições entre páginas preparado, para futuras expansões do portfolio com múltiplas páginas.
|
||||
|
||||
#### Acceptance Criteria
|
||||
|
||||
1. THE Animation_System SHALL criar um componente PageTransition reutilizável
|
||||
2. WHEN uma página carrega, THE PageTransition SHALL aplicar fade in de 0.4s
|
||||
3. THE PageTransition SHALL usar ease-out curve para entrada
|
||||
4. THE PageTransition SHALL ser compatível com Next.js App Router
|
||||
5. IF Reduced_Motion está ativo, THEN THE PageTransition SHALL reduzir duração para 0.15s
|
||||
|
||||
### Requirement 7: Implementar Animações de Reveal em Imagens
|
||||
|
||||
**User Story:** Como usuário, quero ver imagens aparecerem com efeito de reveal elegante, para ter uma experiência visual mais sofisticada.
|
||||
|
||||
#### Acceptance Criteria
|
||||
|
||||
1. WHEN uma imagem entra no Viewport, THE Animation_System SHALL aplicar clip-path reveal animation
|
||||
2. THE Animation_System SHALL usar clip-path: inset() para criar efeito de cortina
|
||||
3. THE Animation_System SHALL combinar reveal com fade in e scale sutil (0.98 → 1)
|
||||
4. THE Animation_System SHALL aplicar blur inicial (8px) que remove durante o reveal
|
||||
5. THE Animation_System SHALL usar duração de 0.9s para o reveal completo
|
||||
6. IF Reduced_Motion está ativo, THEN THE Animation_System SHALL usar apenas fade simples
|
||||
|
||||
### Requirement 8: Implementar Animações de Reveal em Textos
|
||||
|
||||
**User Story:** Como usuário, quero ver títulos e textos aparecerem com efeito de reveal por caractere ou palavra, para ter uma experiência tipográfica premium.
|
||||
|
||||
#### Acceptance Criteria
|
||||
|
||||
1. WHEN um título de seção entra no Viewport, THE Animation_System SHALL aplicar reveal por palavra
|
||||
2. THE Animation_System SHALL usar stagger de 0.04s entre palavras
|
||||
3. THE Animation_System SHALL aplicar blur inicial (6px) e scale (0.95) em cada palavra
|
||||
4. THE Animation_System SHALL usar clip-path: inset(0 100% 0 0) para efeito de slide horizontal
|
||||
5. THE Animation_System SHALL aplicar reveal em títulos de seção (ds-section-title)
|
||||
6. IF Reduced_Motion está ativo, THEN THE Animation_System SHALL mostrar texto completo com fade simples
|
||||
|
||||
### Requirement 9: Otimizar Espaçamentos
|
||||
|
||||
**User Story:** Como usuário, quero ver uma página sem espaços vazios desnecessários, para ter uma experiência visual mais compacta e profissional.
|
||||
|
||||
#### Acceptance Criteria
|
||||
|
||||
1. THE Design_System SHALL reduzir padding vertical das seções de var(--sp-20) para var(--sp-16)
|
||||
2. THE Design_System SHALL reduzir gap entre cards de var(--sp-6) para var(--sp-5)
|
||||
3. THE Hero_Component SHALL reduzir min-height para otimizar espaço vertical
|
||||
4. THE Design_System SHALL manter espaçamentos responsivos em mobile
|
||||
5. THE Design_System SHALL garantir que mudanças não quebrem o layout existente
|
||||
|
||||
### Requirement 10: Garantir Performance e Acessibilidade
|
||||
|
||||
**User Story:** Como usuário com preferência de movimento reduzido, quero que o site respeite minhas configurações de acessibilidade, para ter uma experiência confortável.
|
||||
|
||||
#### Acceptance Criteria
|
||||
|
||||
1. THE Animation_System SHALL detectar prefers-reduced-motion do sistema operacional
|
||||
2. IF Reduced_Motion está ativo, THEN THE Animation_System SHALL desabilitar todas as animações complexas
|
||||
3. IF Reduced_Motion está ativo, THEN THE Animation_System SHALL manter apenas transições de opacidade simples
|
||||
4. THE Animation_System SHALL usar will-change apenas durante animações ativas
|
||||
5. THE Animation_System SHALL remover will-change após conclusão das animações
|
||||
6. THE Animation_System SHALL usar transform e opacity para animações (GPU-accelerated)
|
||||
7. THE Animation_System SHALL evitar animações de propriedades que causam reflow (width, height, margin)
|
||||
8. THE Animation_System SHALL limitar animações simultâneas para manter 60fps
|
||||
|
||||
### Requirement 11: Implementar Smooth Scroll Global
|
||||
|
||||
**User Story:** Como usuário, quero ter scroll suave e fluido em toda a página, para ter uma experiência de navegação premium.
|
||||
|
||||
#### Acceptance Criteria
|
||||
|
||||
1. THE Animation_System SHALL integrar Lenis para smooth scroll global
|
||||
2. THE Animation_System SHALL configurar Lenis com duração de 1.2s
|
||||
3. THE Animation_System SHALL usar easing: [0.25, 0.0, 0.35, 1.0] para o scroll
|
||||
4. THE Animation_System SHALL sincronizar Lenis com requestAnimationFrame
|
||||
5. THE Animation_System SHALL aplicar smooth scroll em navegação por âncoras
|
||||
6. IF Reduced_Motion está ativo, THEN THE Animation_System SHALL desabilitar smooth scroll
|
||||
|
||||
### Requirement 12: Implementar Magnetic Effect em Botões
|
||||
|
||||
**User Story:** Como usuário, quero ver botões principais com efeito magnético sutil ao aproximar o cursor, para ter uma experiência interativa premium.
|
||||
|
||||
#### Acceptance Criteria
|
||||
|
||||
1. WHEN o cursor está próximo (raio de 80px) de um botão principal, THE Animation_System SHALL aplicar magnetic effect
|
||||
2. THE Animation_System SHALL mover o botão em direção ao cursor proporcionalmente à distância
|
||||
3. THE Animation_System SHALL limitar o movimento máximo a 12px em qualquer direção
|
||||
4. THE Animation_System SHALL usar spring physics (stiffness: 150, damping: 15)
|
||||
5. WHEN o cursor sai da área de influência, THE Animation_System SHALL retornar o botão à posição original
|
||||
6. THE Animation_System SHALL aplicar magnetic effect apenas em botões CTA principais
|
||||
7. IF Reduced_Motion está ativo, THEN THE Animation_System SHALL desabilitar magnetic effect
|
||||
|
||||
### Requirement 13: Implementar Cursor Customizado
|
||||
|
||||
**User Story:** Como usuário, quero ver um cursor customizado que reage aos elementos da página, para ter uma experiência visual mais imersiva e premium.
|
||||
|
||||
#### Acceptance Criteria
|
||||
|
||||
1. THE Animation_System SHALL criar um cursor customizado circular de 40px
|
||||
2. THE Animation_System SHALL seguir a posição do mouse com smooth delay de 0.1s
|
||||
3. WHEN o cursor está sobre elementos interativos, THE Animation_System SHALL expandir o cursor para 60px
|
||||
4. WHEN o cursor está sobre links, THE Animation_System SHALL mudar a cor do cursor para var(--slash)
|
||||
5. THE Animation_System SHALL usar mix-blend-mode: difference para contraste automático
|
||||
6. THE Animation_System SHALL ocultar o cursor padrão do sistema
|
||||
7. THE Animation_System SHALL mostrar cursor padrão em dispositivos touch
|
||||
8. IF Reduced_Motion está ativo, THEN THE Animation_System SHALL desabilitar cursor customizado
|
||||
|
||||
### Requirement 14: Implementar Loading States Animados
|
||||
|
||||
**User Story:** Como usuário, quero ver estados de loading elegantes durante carregamento de dados, para ter feedback visual claro do progresso.
|
||||
|
||||
#### Acceptance Criteria
|
||||
|
||||
1. WHEN dados estão carregando, THE Animation_System SHALL exibir skeleton screens animados
|
||||
2. THE Animation_System SHALL usar shimmer effect nos skeletons
|
||||
3. THE Animation_System SHALL manter a estrutura visual da seção durante loading
|
||||
4. THE Animation_System SHALL aplicar fade out suave ao remover skeleton (0.3s)
|
||||
5. THE Animation_System SHALL aplicar fade in + slide up ao mostrar conteúdo real
|
||||
6. IF Reduced_Motion está ativo, THEN THE Animation_System SHALL usar pulse simples sem shimmer
|
||||
|
||||
### Requirement 15: Implementar Micro-interactions em Formulários
|
||||
|
||||
**User Story:** Como usuário, quero ver feedback visual imediato ao interagir com campos de formulário, para ter uma experiência de preenchimento mais agradável.
|
||||
|
||||
#### Acceptance Criteria
|
||||
|
||||
1. WHEN um campo recebe foco, THE Animation_System SHALL aplicar scale de 1.01 e glow effect
|
||||
2. WHEN o usuário digita, THE Animation_System SHALL aplicar pulse sutil no label
|
||||
3. WHEN validação ocorre, THE Animation_System SHALL aplicar shake animation em erros
|
||||
4. WHEN validação é bem-sucedida, THE Animation_System SHALL aplicar checkmark animado
|
||||
5. THE Animation_System SHALL usar spring physics para transições de estado
|
||||
6. IF Reduced_Motion está ativo, THEN THE Animation_System SHALL usar apenas mudanças de cor
|
||||
|
||||
@@ -0,0 +1,419 @@
|
||||
# Implementation Plan: Premium Animations
|
||||
|
||||
## Overview
|
||||
|
||||
Este plano implementa animações premium no portfolio evandro.dev.br usando Framer Motion e Lenis. A implementação segue uma abordagem incremental, começando com setup e quick wins (remoção do logo), seguindo para scroll-triggered animations (maior impacto visual), hover effects, e finalmente features avançadas como parallax, magnetic buttons e cursor customizado.
|
||||
|
||||
Tecnologias: React 19.1.0, Next.js 15.5.9, TypeScript, Framer Motion 12.23.12, Lenis 1.3.18, Tailwind CSS 4.
|
||||
|
||||
## Tasks
|
||||
|
||||
- [x] 1. Setup inicial do sistema de animações
|
||||
- [x] 1.1 Instalar dependências (Framer Motion 12.23.12, Lenis 1.3.18)
|
||||
- Executar `npm install [email protected] [email protected]`
|
||||
- Verificar instalação no package.json
|
||||
- _Requirements: 2, 11_
|
||||
|
||||
- [x] 1.2 Criar arquivo de configuração centralizada
|
||||
- Criar `app/lib/animations/config.ts` com animationConfig (easings, durations, scrollTrigger, stagger, parallax, magnetic, cursor, reducedMotion)
|
||||
- Criar `app/lib/animations/variants.ts` com variant presets (fadeIn, fadeInUp, fadeInDown, fadeInLeft, fadeInRight, scaleIn, imageReveal, textReveal, staggerContainer, reducedMotion)
|
||||
- _Requirements: 2, 3, 4, 5, 7, 8, 10_
|
||||
|
||||
- [x] 1.3 Criar hook useReducedMotion
|
||||
- Criar `app/hooks/useReducedMotion.ts` que detecta prefers-reduced-motion
|
||||
- Usar hook do Framer Motion como base
|
||||
- Retornar boolean indicando se reduced motion está ativo
|
||||
- _Requirements: 10_
|
||||
|
||||
- [x] 1.4 Criar AnimationProvider
|
||||
- Criar `app/providers/AnimationProvider.tsx` com context para configurações globais
|
||||
- Fornecer reducedMotion, easings, durations via context
|
||||
- Criar hook useAnimationConfig para consumir o context
|
||||
- _Requirements: 10_
|
||||
|
||||
- [x] 1.5 Integrar AnimationProvider no root layout
|
||||
- Adicionar AnimationProvider em `app/layout.tsx` envolvendo children
|
||||
- Garantir que provider está acima de todos os componentes
|
||||
- _Requirements: 10_
|
||||
|
||||
- [x] 2. Quick win: Remover logo do Hero
|
||||
- [x] 2.1 Remover fase logo do Hero component
|
||||
- Editar `app/components/Hero.tsx` removendo a fase "logo" do ciclo de animação
|
||||
- Manter apenas a animação de digitação do texto "evandro.dev.br"
|
||||
- Garantir que animação inicia diretamente com typing
|
||||
- Manter todas as outras funcionalidades (botões, links sociais, status)
|
||||
- _Requirements: 1_
|
||||
|
||||
- [x] 2.2 Escrever testes para Hero sem logo
|
||||
- Testar que logo não é renderizada
|
||||
- Testar que texto "evandro.dev.br" é exibido
|
||||
- Testar que animação de typing funciona
|
||||
- _Requirements: 1_
|
||||
|
||||
- [x] 3. Checkpoint - Verificar setup e quick win
|
||||
- Ensure all tests pass, ask the user if questions arise.
|
||||
|
||||
- [ ] 4. Implementar scroll-triggered animations (core)
|
||||
- [~] 4.1 Criar hook useScrollTrigger
|
||||
- Criar `app/hooks/useScrollTrigger.ts` wrapper sobre useInView do Framer Motion
|
||||
- Aceitar options: threshold (default 0.2), once (default true), margin (default "0px")
|
||||
- Retornar ref, isInView, entry
|
||||
- _Requirements: 2_
|
||||
|
||||
- [~] 4.2 Criar componente ScrollReveal
|
||||
- Criar `app/components/animations/ScrollReveal.tsx`
|
||||
- Aceitar props: children, direction (up/down/left/right), distance (default 24), duration (default 0.6), delay (default 0), threshold (default 0.2), once (default true), className
|
||||
- Usar useScrollTrigger e useReducedMotion
|
||||
- Normal: fade in + slide + blur inicial
|
||||
- Reduced motion: apenas fade in simples
|
||||
- _Requirements: 2, 10_
|
||||
|
||||
- [~] 4.3 Escrever testes para ScrollReveal
|
||||
- Testar animação normal (fade + slide + blur)
|
||||
- Testar reduced motion (apenas fade)
|
||||
- Testar threshold e once
|
||||
- _Requirements: 2, 10_
|
||||
|
||||
- [ ] 5. Implementar stagger animations
|
||||
- [~] 5.1 Criar componente StaggerContainer
|
||||
- Criar `app/components/animations/StaggerContainer.tsx`
|
||||
- Aceitar props: children, staggerDelay (default 0.08), initialDelay (default 0), className
|
||||
- Usar motion.div com variants para stagger automático
|
||||
- Ajustar delay para 0.03s se reduced motion ativo
|
||||
- _Requirements: 3, 10_
|
||||
|
||||
- [~] 5.2 Escrever testes para StaggerContainer
|
||||
- Testar stagger delay normal (0.08s)
|
||||
- Testar stagger delay com reduced motion (0.03s)
|
||||
- _Requirements: 3, 10_
|
||||
|
||||
- [ ] 6. Aplicar scroll animations nas seções principais
|
||||
- [~] 6.1 Envolver seções com ScrollReveal
|
||||
- Aplicar ScrollReveal em About, Skills, Experience, Projects, WorkModalities, Contact
|
||||
- Usar direction="up" e configurações padrão
|
||||
- _Requirements: 2_
|
||||
|
||||
- [~] 6.2 Aplicar StaggerContainer em grids de cards
|
||||
- Aplicar em Projects grid
|
||||
- Aplicar em Skills grid
|
||||
- Aplicar em Experience list
|
||||
- _Requirements: 3_
|
||||
|
||||
- [~] 6.3 Aplicar stagger em listas de tags e métricas
|
||||
- Identificar listas de tags em Projects
|
||||
- Identificar métricas em seções
|
||||
- Envolver com StaggerContainer
|
||||
- _Requirements: 3_
|
||||
|
||||
- [~] 7. Checkpoint - Verificar scroll animations
|
||||
- Ensure all tests pass, ask the user if questions arise.
|
||||
|
||||
- [ ] 8. Implementar hover effects sofisticados
|
||||
- [~] 8.1 Criar hover effects para cards
|
||||
- Adicionar motion.div wrapper em componentes de card
|
||||
- Implementar lift effect (translateY: -6px) no hover
|
||||
- Implementar aumento de sombra no hover
|
||||
- Usar spring physics (stiffness: 200, damping: 20)
|
||||
- Reduced motion: apenas mudança de opacidade
|
||||
- _Requirements: 5, 10_
|
||||
|
||||
- [~] 8.2 Criar hover effects para botões
|
||||
- Adicionar motion wrapper em botões principais
|
||||
- Implementar scale de 1.03 no hover
|
||||
- Adicionar glow effect sutil em elementos com cor --slash
|
||||
- Usar spring physics
|
||||
- Reduced motion: apenas mudança de opacidade
|
||||
- _Requirements: 5, 10_
|
||||
|
||||
- [~] 8.3 Criar hover effects para links sociais
|
||||
- Adicionar motion wrapper em links sociais
|
||||
- Implementar rotação sutil (-3deg a 3deg) no hover
|
||||
- Usar spring physics
|
||||
- Reduced motion: apenas mudança de opacidade
|
||||
- _Requirements: 5, 10_
|
||||
|
||||
- [~] 8.4 Escrever testes para hover effects
|
||||
- Testar lift effect em cards
|
||||
- Testar scale em botões
|
||||
- Testar rotação em links sociais
|
||||
- Testar reduced motion (apenas opacidade)
|
||||
- _Requirements: 5, 10_
|
||||
|
||||
- [ ] 9. Implementar smooth scroll global com Lenis
|
||||
- [~] 9.1 Criar LenisProvider
|
||||
- Criar `app/providers/LenisProvider.tsx`
|
||||
- Inicializar Lenis com duration: 1.2, easing: [0.25, 0.0, 0.35, 1.0]
|
||||
- Sincronizar com requestAnimationFrame
|
||||
- Fornecer instância via context
|
||||
- Desabilitar se reduced motion ativo
|
||||
- _Requirements: 11, 10_
|
||||
|
||||
- [~] 9.2 Integrar LenisProvider no root layout
|
||||
- Adicionar LenisProvider em `app/layout.tsx`
|
||||
- Garantir que está acima de AnimationProvider
|
||||
- _Requirements: 11_
|
||||
|
||||
- [~] 9.3 Aplicar smooth scroll em navegação por âncoras
|
||||
- Identificar links de navegação interna
|
||||
- Configurar Lenis para smooth scroll em âncoras
|
||||
- _Requirements: 11_
|
||||
|
||||
- [~] 9.4 Escrever testes para smooth scroll
|
||||
- Testar inicialização do Lenis
|
||||
- Testar desabilitação com reduced motion
|
||||
- _Requirements: 11, 10_
|
||||
|
||||
- [~] 10. Checkpoint - Verificar hover effects e smooth scroll
|
||||
- Ensure all tests pass, ask the user if questions arise.
|
||||
|
||||
- [ ] 11. Implementar parallax sutil em backgrounds
|
||||
- [~] 11.1 Criar hook useParallax
|
||||
- Criar `app/hooks/useParallax.ts`
|
||||
- Usar useScroll e useTransform do Framer Motion
|
||||
- Aceitar options: speed (default 0.5), direction (vertical/horizontal), disabled
|
||||
- Retornar ref e style
|
||||
- _Requirements: 4_
|
||||
|
||||
- [~] 11.2 Criar componente ParallaxElement
|
||||
- Criar `app/components/animations/ParallaxElement.tsx`
|
||||
- Usar useParallax e useReducedMotion
|
||||
- Normal: movimento parallax suave
|
||||
- Reduced motion: elemento estático
|
||||
- _Requirements: 4, 10_
|
||||
|
||||
- [~] 11.3 Aplicar parallax no Hero
|
||||
- Aplicar ParallaxElement no grid de fundo do Hero
|
||||
- Aplicar ParallaxElement no gradiente radial do Hero
|
||||
- Usar speed: 0.3 (30% mais lento)
|
||||
- _Requirements: 4_
|
||||
|
||||
- [~] 11.4 Escrever testes para parallax
|
||||
- Testar cálculo de posição baseado em scroll
|
||||
- Testar desabilitação com reduced motion
|
||||
- _Requirements: 4, 10_
|
||||
|
||||
- [ ] 12. Implementar reveal animado de imagens
|
||||
- [~] 12.1 Criar componente ImageReveal
|
||||
- Criar `app/components/animations/ImageReveal.tsx`
|
||||
- Implementar clip-path reveal + fade in + scale (0.98 → 1) + blur (8px → 0px)
|
||||
- Duração: 0.9s
|
||||
- Usar useScrollTrigger para disparar quando entra no viewport
|
||||
- Reduced motion: apenas fade in simples
|
||||
- _Requirements: 7, 10_
|
||||
|
||||
- [~] 12.2 Aplicar ImageReveal em imagens do portfolio
|
||||
- Identificar imagens em Projects
|
||||
- Identificar imagens em About
|
||||
- Substituir tags img por ImageReveal
|
||||
- _Requirements: 7_
|
||||
|
||||
- [~] 12.3 Escrever testes para ImageReveal
|
||||
- Testar clip-path reveal animation
|
||||
- Testar reduced motion (apenas fade)
|
||||
- _Requirements: 7, 10_
|
||||
|
||||
- [ ] 13. Implementar reveal animado de textos
|
||||
- [~] 13.1 Criar componente TextReveal
|
||||
- Criar `app/components/animations/TextReveal.tsx`
|
||||
- Implementar reveal por palavra com blur (6px → 0px) + scale (0.95 → 1) + clip-path slide
|
||||
- Stagger delay: 0.04s entre palavras
|
||||
- Usar useScrollTrigger para disparar quando entra no viewport
|
||||
- Reduced motion: texto completo com fade in simples
|
||||
- _Requirements: 8, 10_
|
||||
|
||||
- [~] 13.2 Aplicar TextReveal em títulos de seção
|
||||
- Identificar títulos com classe ds-section-title
|
||||
- Substituir por TextReveal component
|
||||
- _Requirements: 8_
|
||||
|
||||
- [~] 13.3 Escrever testes para TextReveal
|
||||
- Testar reveal por palavra
|
||||
- Testar stagger delay
|
||||
- Testar reduced motion (fade simples)
|
||||
- _Requirements: 8, 10_
|
||||
|
||||
- [~] 14. Checkpoint - Verificar parallax e reveals
|
||||
- Ensure all tests pass, ask the user if questions arise.
|
||||
|
||||
- [ ] 15. Implementar transições de página
|
||||
- [~] 15.1 Criar componente PageTransition
|
||||
- Criar `app/components/animations/PageTransition.tsx`
|
||||
- Implementar fade in de 0.4s com ease-out
|
||||
- Reduced motion: fade in de 0.15s
|
||||
- Compatível com Next.js App Router
|
||||
- _Requirements: 6, 10_
|
||||
|
||||
- [~] 15.2 Aplicar PageTransition nas páginas
|
||||
- Envolver conteúdo de cada página com PageTransition
|
||||
- Garantir compatibilidade com App Router
|
||||
- _Requirements: 6_
|
||||
|
||||
- [~] 15.3 Escrever testes para PageTransition
|
||||
- Testar fade in normal (0.4s)
|
||||
- Testar fade in com reduced motion (0.15s)
|
||||
- _Requirements: 6, 10_
|
||||
|
||||
- [ ] 16. Implementar magnetic effect em botões
|
||||
- [~] 16.1 Criar hook useMagneticEffect
|
||||
- Criar `app/hooks/useMagneticEffect.ts`
|
||||
- Rastrear posição do mouse
|
||||
- Calcular distância ao elemento
|
||||
- Aplicar transform proporcional com spring physics (stiffness: 150, damping: 15)
|
||||
- Aceitar options: radius (default 80), strength (default 12), disabled
|
||||
- Retornar ref e style
|
||||
- _Requirements: 12_
|
||||
|
||||
- [~] 16.2 Aplicar magnetic effect em botões CTA principais
|
||||
- Identificar botões CTA principais
|
||||
- Adicionar useMagneticEffect
|
||||
- Desabilitar se reduced motion ativo
|
||||
- _Requirements: 12, 10_
|
||||
|
||||
- [~] 16.3 Escrever testes para magnetic effect
|
||||
- Testar cálculo de distância
|
||||
- Testar movimento proporcional
|
||||
- Testar desabilitação com reduced motion
|
||||
- _Requirements: 12, 10_
|
||||
|
||||
- [ ] 17. Implementar cursor customizado
|
||||
- [~] 17.1 Criar CursorProvider e CustomCursor component
|
||||
- Criar `app/providers/CursorProvider.tsx` com context
|
||||
- Criar `app/components/animations/CustomCursor.tsx`
|
||||
- Implementar cursor circular de 40px que segue o mouse com delay de 0.1s
|
||||
- Expandir para 60px sobre elementos interativos
|
||||
- Mudar cor para var(--slash) sobre links
|
||||
- Usar mix-blend-mode: difference
|
||||
- Ocultar cursor padrão do sistema
|
||||
- Mostrar cursor padrão em touch devices
|
||||
- Desabilitar se reduced motion ativo
|
||||
- _Requirements: 13, 10_
|
||||
|
||||
- [~] 17.2 Integrar CursorProvider no root layout
|
||||
- Adicionar CursorProvider em `app/layout.tsx`
|
||||
- Garantir que CustomCursor é renderizado
|
||||
- _Requirements: 13_
|
||||
|
||||
- [~] 17.3 Adicionar data attributes em elementos interativos
|
||||
- Adicionar data-cursor="expand" em botões e cards
|
||||
- Adicionar data-cursor="link" em links
|
||||
- Configurar CustomCursor para reagir aos data attributes
|
||||
- _Requirements: 13_
|
||||
|
||||
- [~] 17.4 Escrever testes para cursor customizado
|
||||
- Testar seguimento do mouse
|
||||
- Testar expansão sobre interativos
|
||||
- Testar mudança de cor sobre links
|
||||
- Testar desabilitação em touch devices
|
||||
- Testar desabilitação com reduced motion
|
||||
- _Requirements: 13, 10_
|
||||
|
||||
- [~] 18. Checkpoint - Verificar features avançadas
|
||||
- Ensure all tests pass, ask the user if questions arise.
|
||||
|
||||
- [ ] 19. Implementar loading states animados
|
||||
- [~] 19.1 Criar componente SkeletonLoader
|
||||
- Criar `app/components/animations/SkeletonLoader.tsx`
|
||||
- Implementar shimmer effect
|
||||
- Manter estrutura visual da seção
|
||||
- Reduced motion: pulse simples sem shimmer
|
||||
- _Requirements: 14, 10_
|
||||
|
||||
- [~] 19.2 Criar transições de loading para conteúdo real
|
||||
- Implementar fade out suave do skeleton (0.3s)
|
||||
- Implementar fade in + slide up do conteúdo real
|
||||
- _Requirements: 14_
|
||||
|
||||
- [~] 19.3 Aplicar loading states em seções com dados dinâmicos
|
||||
- Identificar seções que carregam dados
|
||||
- Adicionar SkeletonLoader como fallback
|
||||
- _Requirements: 14_
|
||||
|
||||
- [~] 19.4 Escrever testes para loading states
|
||||
- Testar shimmer effect
|
||||
- Testar transição de skeleton para conteúdo
|
||||
- Testar reduced motion (pulse simples)
|
||||
- _Requirements: 14, 10_
|
||||
|
||||
- [ ] 20. Implementar micro-interactions em formulários
|
||||
- [~] 20.1 Criar animações de foco em campos
|
||||
- Adicionar motion wrapper em campos de formulário
|
||||
- Implementar scale de 1.01 e glow effect no foco
|
||||
- Usar spring physics
|
||||
- _Requirements: 15_
|
||||
|
||||
- [~] 20.2 Criar animações de digitação
|
||||
- Implementar pulse sutil no label quando usuário digita
|
||||
- Usar spring physics
|
||||
- _Requirements: 15_
|
||||
|
||||
- [~] 20.3 Criar animações de validação
|
||||
- Implementar shake animation para erros
|
||||
- Implementar checkmark animado para sucesso
|
||||
- Usar spring physics
|
||||
- Reduced motion: apenas mudanças de cor
|
||||
- _Requirements: 15, 10_
|
||||
|
||||
- [~] 20.4 Escrever testes para micro-interactions
|
||||
- Testar animação de foco
|
||||
- Testar pulse no label
|
||||
- Testar shake em erros
|
||||
- Testar checkmark em sucesso
|
||||
- Testar reduced motion (apenas cores)
|
||||
- _Requirements: 15, 10_
|
||||
|
||||
- [ ] 21. Otimizar espaçamentos
|
||||
- [~] 21.1 Reduzir padding vertical das seções
|
||||
- Alterar padding de var(--sp-20) para var(--sp-16) em seções
|
||||
- Manter espaçamentos responsivos em mobile
|
||||
- _Requirements: 9_
|
||||
|
||||
- [~] 21.2 Reduzir gap entre cards
|
||||
- Alterar gap de var(--sp-6) para var(--sp-5) em grids
|
||||
- Garantir que layout não quebra
|
||||
- _Requirements: 9_
|
||||
|
||||
- [~] 21.3 Otimizar min-height do Hero
|
||||
- Reduzir min-height do Hero para otimizar espaço vertical
|
||||
- Manter proporções visuais adequadas
|
||||
- _Requirements: 9_
|
||||
|
||||
- [~] 21.4 Escrever testes para espaçamentos
|
||||
- Testar padding das seções
|
||||
- Testar gap entre cards
|
||||
- Testar min-height do Hero
|
||||
- Testar responsividade em mobile
|
||||
- _Requirements: 9_
|
||||
|
||||
- [ ] 22. Otimizações de performance
|
||||
- [~] 22.1 Implementar will-change dinâmico
|
||||
- Adicionar will-change apenas durante animações ativas
|
||||
- Remover will-change após conclusão
|
||||
- _Requirements: 10_
|
||||
|
||||
- [~] 22.2 Auditar propriedades animadas
|
||||
- Garantir que apenas transform e opacity são animados
|
||||
- Remover animações de propriedades que causam reflow (width, height, margin)
|
||||
- _Requirements: 10_
|
||||
|
||||
- [~] 22.3 Limitar animações simultâneas
|
||||
- Implementar throttling para manter 60fps
|
||||
- Priorizar animações visíveis no viewport
|
||||
- _Requirements: 10_
|
||||
|
||||
- [~] 22.4 Escrever testes de performance
|
||||
- Testar will-change dinâmico
|
||||
- Testar que apenas transform/opacity são animados
|
||||
- Testar throttling de animações
|
||||
- _Requirements: 10_
|
||||
|
||||
- [~] 23. Final checkpoint - Verificar todas as animações
|
||||
- Ensure all tests pass, ask the user if questions arise.
|
||||
|
||||
## Notes
|
||||
|
||||
- Tasks marcadas com `*` são opcionais e podem ser puladas para MVP mais rápido
|
||||
- Cada task referencia requirements específicos para rastreabilidade
|
||||
- Checkpoints garantem validação incremental
|
||||
- Todas as animações respeitam prefers-reduced-motion para acessibilidade
|
||||
- Performance é prioridade: apenas transform e opacity são animados
|
||||
- Sistema modular permite reutilização de componentes e hooks
|
||||
Reference in new issue
Block a user