sinapse-ai 9.3.0 → 9.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/CLAUDE.md +56 -343
- package/.claude/rules/agent-authority.md +6 -0
- package/.claude/rules/agent-handoff.md +5 -0
- package/.claude/rules/cross-squad-routing.md +5 -0
- package/.claude/rules/hook-governance.md +6 -0
- package/.claude/rules/mcp-usage.md +3 -1
- package/.claude/rules/safe-collaboration.md +10 -0
- package/.claude/rules/security-data-protection.md +9 -0
- package/.claude/rules/squad-awareness.md +3 -1
- package/.claude/rules/tool-examples.md +6 -0
- package/.claude/rules/workflow-execution.md +7 -0
- package/.codex/agents/analyst.md +253 -72
- package/.codex/agents/architect.md +455 -68
- package/.codex/agents/data-engineer.md +492 -106
- package/.codex/agents/developer.md +560 -0
- package/.codex/agents/devops.md +518 -69
- package/.codex/agents/product-lead.md +335 -0
- package/.codex/agents/project-lead.md +377 -0
- package/.codex/agents/quality-gate.md +449 -0
- package/.codex/agents/sinapse-orqx.md +9 -7
- package/.codex/agents/sprint-lead.md +287 -0
- package/.codex/agents/squad-creator.md +344 -0
- package/.codex/agents/ux-design-expert.md +495 -0
- package/.codex/delegation-matrix.json +756 -44
- package/.codex/handoff-packet.schema.json +30 -6
- package/.sinapse-ai/data/entity-registry.yaml +175 -363
- package/.sinapse-ai/data/registry-update-log.jsonl +16 -0
- package/.sinapse-ai/development/agents/analyst.md +90 -0
- package/.sinapse-ai/development/agents/architect.md +73 -0
- package/.sinapse-ai/development/agents/developer.md +69 -0
- package/.sinapse-ai/development/agents/devops.md +117 -0
- package/.sinapse-ai/development/agents/quality-gate.md +85 -0
- package/.sinapse-ai/development/checklists/agent-quality-gate.md +27 -0
- package/.sinapse-ai/development/checklists/brownfield-compatibility-checklist.md +20 -0
- package/.sinapse-ai/development/checklists/code-review-checklist.md +106 -0
- package/.sinapse-ai/development/checklists/issue-triage-checklist.md +9 -0
- package/.sinapse-ai/development/checklists/memory-audit-checklist.md +16 -0
- package/.sinapse-ai/development/checklists/pr-quality-checklist.md +72 -0
- package/.sinapse-ai/development/checklists/security-deployment-checklist.md +54 -0
- package/.sinapse-ai/development/checklists/self-critique-checklist.md +19 -1
- package/.sinapse-ai/development/skills/debug.md +57 -0
- package/.sinapse-ai/development/skills/fast-review.md +69 -0
- package/.sinapse-ai/development/skills/research-synthesis.md +77 -0
- package/.sinapse-ai/development/skills/security-scan.md +73 -0
- package/.sinapse-ai/development/skills/verify.md +53 -0
- package/.sinapse-ai/development/templates/squad/agent-template.md +17 -4
- package/.sinapse-ai/development/templates/squad/checklist-template.md +13 -5
- package/.sinapse-ai/development/templates/squad/task-template.md +7 -0
- package/.sinapse-ai/development/templates/squad/workflow-template.yaml +7 -0
- package/.sinapse-ai/development/workflows/fast-track.yaml +87 -0
- package/.sinapse-ai/infrastructure/scripts/validate-codex-delegation.js +3 -1
- package/.sinapse-ai/install-manifest.yaml +71 -35
- package/docs/codex-integration-process.md +22 -0
- package/docs/codex-parity-program.md +27 -0
- package/docs/ide-integration.md +36 -0
- package/package.json +1 -1
- package/squads/claude-code-mastery/knowledge-base/claude-code-internals-reference.md +927 -0
- package/squads/squad-brand/knowledge-base/archetype-brand-mapping.md +12 -1
- package/squads/squad-brand/knowledge-base/brand-activism-cultural-branding.md +216 -0
- package/squads/squad-brand/knowledge-base/brand-audit-criteria.md +58 -0
- package/squads/squad-brand/knowledge-base/brand-digital-strategy.md +188 -0
- package/squads/squad-brand/knowledge-base/brand-legal-ip.md +222 -0
- package/squads/squad-brand/knowledge-base/brand-naming-framework.md +163 -0
- package/squads/squad-brand/knowledge-base/branding-master-reference.md +1001 -0
- package/squads/squad-brand/knowledge-base/color-psychology.md +25 -12
- package/squads/squad-brand/knowledge-base/employer-personal-branding.md +206 -0
- package/squads/squad-brand/knowledge-base/routing-catalog.md +34 -0
- package/squads/squad-brand/knowledge-base/sonic-branding-principles.md +6 -1
- package/squads/squad-brand/knowledge-base/typography-personality.md +34 -0
- package/squads/squad-claude/knowledge-base/context-window-optimization.md +334 -0
- package/squads/squad-claude/knowledge-base/knowledge-architecture-reference.md +403 -0
- package/squads/squad-claude/knowledge-base/memory-systems-reference.md +412 -0
- package/squads/squad-claude/knowledge-base/obsidian-claude-integration.md +423 -0
- package/squads/squad-claude/knowledge-base/retrieval-augmented-generation.md +320 -0
- package/squads/squad-claude/knowledge-base/skill-creation-patterns.md +380 -0
- package/squads/squad-claude/knowledge-base/swarm-orchestration-patterns.md +411 -0
- package/squads/squad-cloning/knowledge-base/clone-quality-assurance.md +211 -0
- package/squads/squad-cloning/knowledge-base/confidence-scoring.md +51 -0
- package/squads/squad-cloning/knowledge-base/cross-squad-deployment.md +47 -0
- package/squads/squad-cloning/knowledge-base/ethical-guidelines.md +237 -0
- package/squads/squad-cloning/knowledge-base/knowledge-graph-for-clones.md +295 -0
- package/squads/squad-cloning/knowledge-base/memory-architecture-for-clones.md +229 -0
- package/squads/squad-cloning/knowledge-base/multi-agent-deployment-patterns.md +320 -0
- package/squads/squad-cloning/knowledge-base/skill-standard-for-clones.md +262 -0
- package/squads/squad-cloning/knowledge-base/sop-extraction-guide.md +243 -0
- package/squads/squad-commercial/knowledge-base/account-based-selling.md +206 -0
- package/squads/squad-commercial/knowledge-base/ai-as-competitive-infrastructure.md +14 -0
- package/squads/squad-commercial/knowledge-base/ai-in-sales.md +199 -0
- package/squads/squad-commercial/knowledge-base/brazilian-sales-context.md +195 -0
- package/squads/squad-commercial/knowledge-base/customer-success-operations.md +83 -2
- package/squads/squad-commercial/knowledge-base/prospecting-pipeline-generation.md +69 -0
- package/squads/squad-commercial/knowledge-base/sales-enablement-playbook.md +260 -0
- package/squads/squad-commercial/knowledge-base/sales-methodology-comparison.md +185 -0
- package/squads/squad-commercial/knowledge-base/sales-revenue-master-reference.md +1123 -0
- package/squads/squad-content/knowledge-base/brazilian-content-context.md +176 -0
- package/squads/squad-content/knowledge-base/competitor-analysis-methods.md +40 -1
- package/squads/squad-content/knowledge-base/content-architecture-taxonomy.md +206 -0
- package/squads/squad-content/knowledge-base/content-formats-encyclopedia.md +58 -1
- package/squads/squad-content/knowledge-base/content-references-bibliography.md +130 -0
- package/squads/squad-content/knowledge-base/content-strategy-master-reference.md +1097 -0
- package/squads/squad-content/knowledge-base/content-tech-stack.md +150 -0
- package/squads/squad-content/knowledge-base/copywriting-formulas-library.md +188 -0
- package/squads/squad-content/knowledge-base/email-newsletter-strategy.md +161 -0
- package/squads/squad-content/knowledge-base/platform-algorithm-intelligence.md +86 -1
- package/squads/squad-content/knowledge-base/social-algorithms-master-reference.md +1007 -0
- package/squads/squad-content/knowledge-base/video-audio-content-playbook.md +218 -0
- package/squads/squad-copy/knowledge-base/ai-copy-production.md +254 -0
- package/squads/squad-copy/knowledge-base/brazilian-copywriting-context.md +242 -0
- package/squads/squad-copy/knowledge-base/email-copywriting-system.md +299 -0
- package/squads/squad-copy/knowledge-base/landing-page-copy-architecture.md +267 -0
- package/squads/squad-copy/knowledge-base/power-words-catalog.md +205 -0
- package/squads/squad-copy/knowledge-base/seo-copywriting.md +255 -0
- package/squads/squad-copy/knowledge-base/video-script-copywriting.md +239 -0
- package/squads/squad-council/knowledge-base/brand-strategy-models.md +193 -0
- package/squads/squad-council/knowledge-base/growth-strategy-models.md +267 -0
- package/squads/squad-council/knowledge-base/innovation-disruption-frameworks.md +193 -0
- package/squads/squad-council/knowledge-base/market-analysis-frameworks.md +240 -0
- package/squads/squad-council/knowledge-base/organizational-leadership-models.md +212 -0
- package/squads/squad-council/knowledge-base/sales-strategy-models.md +215 -0
- package/squads/squad-courses/knowledge-base/course-launch-strategy.md +251 -0
- package/squads/squad-courses/knowledge-base/domain-advocacia-curriculum.md +385 -0
- package/squads/squad-courses/knowledge-base/domain-contabilidade-curriculum.md +266 -0
- package/squads/squad-courses/knowledge-base/platform-comparison.md +68 -0
- package/squads/squad-courses/knowledge-base/video-production-guide.md +70 -0
- package/squads/squad-cybersecurity/knowledge-base/cloud-security-reference.md +363 -0
- package/squads/squad-cybersecurity/knowledge-base/compliance-frameworks.md +273 -0
- package/squads/squad-cybersecurity/knowledge-base/database-security.md +438 -0
- package/squads/squad-cybersecurity/knowledge-base/incident-response-playbook.md +420 -0
- package/squads/squad-cybersecurity/knowledge-base/network-security-reference.md +477 -0
- package/squads/squad-cybersecurity/knowledge-base/penetration-testing-methodology.md +350 -0
- package/squads/squad-cybersecurity/knowledge-base/vulnerability-management.md +349 -0
- package/squads/squad-design/knowledge-base/brazilian-design-context.md +223 -0
- package/squads/squad-design/knowledge-base/component-api-patterns.md +208 -4
- package/squads/squad-design/knowledge-base/design-system-master-reference.md +1302 -0
- package/squads/squad-design/knowledge-base/design-systems-frameworks.md +91 -1
- package/squads/squad-design/knowledge-base/responsive-modern-css.md +96 -4
- package/squads/squad-design/knowledge-base/wcag-aria-reference.md +117 -5
- package/squads/squad-design/knowledge-base/web-performance-reference.md +127 -4
- package/squads/squad-finance/knowledge-base/brazilian-taxation.md +263 -0
- package/squads/squad-finance/knowledge-base/contabilidade-master-reference.md +998 -0
- package/squads/squad-finance/knowledge-base/finance-master-reference.md +946 -0
- package/squads/squad-finance/knowledge-base/financial-reporting-analysis.md +316 -0
- package/squads/squad-finance/knowledge-base/fintech-brazilian-context.md +242 -0
- package/squads/squad-finance/knowledge-base/fpa-planning-frameworks.md +286 -0
- package/squads/squad-finance/knowledge-base/ma-and-transactions.md +285 -0
- package/squads/squad-finance/knowledge-base/risk-management.md +233 -0
- package/squads/squad-finance/knowledge-base/startups-venture-capital.md +337 -0
- package/squads/squad-growth/knowledge-base/ai-growth-playbook.md +216 -0
- package/squads/squad-growth/knowledge-base/attribution-models.md +78 -0
- package/squads/squad-growth/knowledge-base/brazilian-growth-context.md +208 -0
- package/squads/squad-growth/knowledge-base/community-led-growth.md +175 -0
- package/squads/squad-growth/knowledge-base/content-marketing-flywheel.md +190 -0
- package/squads/squad-growth/knowledge-base/email-lifecycle-framework.md +192 -0
- package/squads/squad-growth/knowledge-base/growth-frameworks-catalog.md +82 -0
- package/squads/squad-growth/knowledge-base/growth-master-reference.md +1168 -0
- package/squads/squad-growth/knowledge-base/routing-catalog.md +53 -11
- package/squads/squad-paidmedia/knowledge-base/audiences-segmentation-deep.md +285 -0
- package/squads/squad-paidmedia/knowledge-base/creative-strategy-deep.md +294 -0
- package/squads/squad-paidmedia/knowledge-base/google-ads-account-architecture.md +87 -0
- package/squads/squad-paidmedia/knowledge-base/meta-ads-campaign-architecture.md +76 -0
- package/squads/squad-paidmedia/knowledge-base/paid-media-metrics-reference.md +117 -0
- package/squads/squad-paidmedia/knowledge-base/paid-traffic-master-reference.md +1308 -0
- package/squads/squad-paidmedia/knowledge-base/routing-catalog.md +95 -18
- package/squads/squad-paidmedia/knowledge-base/traffic-masters-frameworks.md +71 -0
- package/squads/squad-product/knowledge-base/brazilian-product-context.md +284 -0
- package/squads/squad-product/knowledge-base/discovery-methodology-playbook.md +141 -0
- package/squads/squad-product/knowledge-base/pm-frameworks-reference.md +125 -9
- package/squads/squad-product/knowledge-base/product-analytics-formulas.md +72 -0
- package/squads/squad-product/knowledge-base/product-led-growth-reference.md +155 -13
- package/squads/squad-product/knowledge-base/product-market-fit-framework.md +222 -0
- package/squads/squad-product/knowledge-base/routing-catalog.md +32 -0
- package/squads/squad-research/knowledge-base/agentic-second-brain-reference.md +591 -0
- package/squads/squad-research/knowledge-base/ai-augmented-research.md +212 -0
- package/squads/squad-research/knowledge-base/brazilian-market-research-sources.md +197 -0
- package/squads/squad-research/knowledge-base/community-platforms-reference.md +786 -0
- package/squads/squad-research/knowledge-base/community-research-methods.md +194 -0
- package/squads/squad-research/knowledge-base/mixed-methods-research-design.md +168 -0
- package/squads/squad-research/knowledge-base/network-effects-analysis.md +192 -0
- package/squads/squad-research/knowledge-base/qualitative-research-deep-methods.md +202 -0
- package/squads/squad-research/knowledge-base/quantitative-research-methods.md +208 -0
- package/squads/squad-research/knowledge-base/research-frameworks-encyclopedia.md +40 -0
- package/squads/squad-research/knowledge-base/research-synthesis-frameworks.md +223 -0
- package/squads/squad-storytelling/knowledge-base/brand-mythology-framework.md +236 -0
- package/squads/squad-storytelling/knowledge-base/brazilian-storytelling-context.md +237 -0
- package/squads/squad-storytelling/knowledge-base/data-storytelling.md +232 -0
- package/squads/squad-storytelling/knowledge-base/improv-storytelling.md +226 -0
- package/squads/squad-storytelling/knowledge-base/persuasion-narrative-techniques.md +269 -0
- package/squads/squad-storytelling/knowledge-base/social-movement-narratives.md +191 -0
- package/squads/squad-storytelling/knowledge-base/video-storytelling.md +252 -0
- package/squads/claude-code-mastery/data/swarm-orchestration-patterns.yaml +0 -378
- package/squads/squad-animations/knowledge-base/framer-motion-complete-reference.md +0 -710
- package/squads/squad-animations/knowledge-base/web-animations-api-view-transitions.md +0 -478
|
@@ -1,710 +0,0 @@
|
|
|
1
|
-
# Framer Motion — Complete Reference
|
|
2
|
-
|
|
3
|
-
> Guia definitivo de Framer Motion para animacoes React de nivel producao.
|
|
4
|
-
> Framer Motion e a biblioteca de animacao mais adotada em React/Next.js (23K+ stars).
|
|
5
|
-
> Ideal para produtos, SaaS, e micro-interactions. GSAP e melhor para scroll storytelling complexo.
|
|
6
|
-
|
|
7
|
-
---
|
|
8
|
-
|
|
9
|
-
## Decision: Quando usar Framer Motion vs GSAP
|
|
10
|
-
|
|
11
|
-
| Situacao | Use |
|
|
12
|
-
|----------|-----|
|
|
13
|
-
| Produto React/Next.js (SaaS, app) | Framer Motion |
|
|
14
|
-
| Website criativo/portfolio/agencia | GSAP + Lenis |
|
|
15
|
-
| Micro-interactions em componentes | Framer Motion |
|
|
16
|
-
| Timeline complexo, scroll pinning | GSAP |
|
|
17
|
-
| Shared element transitions | Framer Motion (layout prop) |
|
|
18
|
-
| SVG morph/draw complexo | GSAP (DrawSVG, MorphSVG) |
|
|
19
|
-
| Physics-based UI | Framer Motion (spring) |
|
|
20
|
-
| 60fps animacao em 1000+ elementos | GSAP (mais performatico) |
|
|
21
|
-
|
|
22
|
-
---
|
|
23
|
-
|
|
24
|
-
## Setup
|
|
25
|
-
|
|
26
|
-
```bash
|
|
27
|
-
npm install framer-motion
|
|
28
|
-
```
|
|
29
|
-
|
|
30
|
-
### Bundle size (importante para decisao)
|
|
31
|
-
- `framer-motion` completo: ~32KB gzip
|
|
32
|
-
- `motion` (alias moderno): ~32KB gzip
|
|
33
|
-
- Importacoes seletivas: usar `m` em vez de `motion` para menor bundle
|
|
34
|
-
|
|
35
|
-
```tsx
|
|
36
|
-
// Tree-shakeable — menor bundle
|
|
37
|
-
import { m, LazyMotion, domAnimation } from 'framer-motion';
|
|
38
|
-
|
|
39
|
-
function App() {
|
|
40
|
-
return (
|
|
41
|
-
<LazyMotion features={domAnimation}>
|
|
42
|
-
<m.div animate={{ opacity: 1 }} />
|
|
43
|
-
</LazyMotion>
|
|
44
|
-
);
|
|
45
|
-
}
|
|
46
|
-
```
|
|
47
|
-
|
|
48
|
-
---
|
|
49
|
-
|
|
50
|
-
## Fundamentos: motion.* Components
|
|
51
|
-
|
|
52
|
-
O `motion.div` e um wrapper que adiciona capacidades de animacao a qualquer elemento HTML/SVG.
|
|
53
|
-
|
|
54
|
-
```tsx
|
|
55
|
-
import { motion } from 'framer-motion';
|
|
56
|
-
|
|
57
|
-
// Animacao simples de entrada
|
|
58
|
-
<motion.div
|
|
59
|
-
initial={{ opacity: 0, y: 20 }}
|
|
60
|
-
animate={{ opacity: 1, y: 0 }}
|
|
61
|
-
transition={{ duration: 0.5, ease: [0.16, 1, 0.3, 1] }}
|
|
62
|
-
/>
|
|
63
|
-
|
|
64
|
-
// Com saida
|
|
65
|
-
<motion.div
|
|
66
|
-
initial={{ opacity: 0 }}
|
|
67
|
-
animate={{ opacity: 1 }}
|
|
68
|
-
exit={{ opacity: 0, y: -20 }}
|
|
69
|
-
/>
|
|
70
|
-
```
|
|
71
|
-
|
|
72
|
-
### Propriedades principais
|
|
73
|
-
|
|
74
|
-
| Prop | Tipo | Descricao |
|
|
75
|
-
|------|------|-----------|
|
|
76
|
-
| `initial` | TargetAndTransition | Estado inicial (antes de animar) |
|
|
77
|
-
| `animate` | TargetAndTransition | Estado animado (alvo) |
|
|
78
|
-
| `exit` | TargetAndTransition | Estado de saida (requer AnimatePresence) |
|
|
79
|
-
| `transition` | Transition | Configuracao de timing/easing/spring |
|
|
80
|
-
| `whileHover` | TargetAndTransition | Estado durante hover |
|
|
81
|
-
| `whileTap` | TargetAndTransition | Estado durante press/tap |
|
|
82
|
-
| `whileDrag` | TargetAndTransition | Estado durante drag |
|
|
83
|
-
| `whileInView` | TargetAndTransition | Estado quando visivel no viewport |
|
|
84
|
-
| `variants` | Variants | Sistema de estados nomeados |
|
|
85
|
-
| `layout` | boolean/string | Ativar FLIP layout animations |
|
|
86
|
-
| `layoutId` | string | Shared element transitions |
|
|
87
|
-
| `drag` | boolean/string | Tornar draggable |
|
|
88
|
-
| `style` | MotionStyle | Motion values em style |
|
|
89
|
-
|
|
90
|
-
---
|
|
91
|
-
|
|
92
|
-
## Variants — Sistema de Estados
|
|
93
|
-
|
|
94
|
-
Variants permitem definir estados nomeados e coordenar animacoes entre pai e filhos.
|
|
95
|
-
|
|
96
|
-
```tsx
|
|
97
|
-
// Container + filhos com stagger
|
|
98
|
-
const containerVariants = {
|
|
99
|
-
hidden: { opacity: 0 },
|
|
100
|
-
visible: {
|
|
101
|
-
opacity: 1,
|
|
102
|
-
transition: {
|
|
103
|
-
staggerChildren: 0.1, // Delay entre cada filho
|
|
104
|
-
delayChildren: 0.2, // Delay inicial antes do primeiro filho
|
|
105
|
-
when: 'beforeChildren', // Container anima ANTES dos filhos
|
|
106
|
-
},
|
|
107
|
-
},
|
|
108
|
-
exit: {
|
|
109
|
-
opacity: 0,
|
|
110
|
-
transition: { staggerChildren: 0.05, staggerDirection: -1 }
|
|
111
|
-
}
|
|
112
|
-
};
|
|
113
|
-
|
|
114
|
-
const itemVariants = {
|
|
115
|
-
hidden: { opacity: 0, y: 30, scale: 0.95 },
|
|
116
|
-
visible: {
|
|
117
|
-
opacity: 1,
|
|
118
|
-
y: 0,
|
|
119
|
-
scale: 1,
|
|
120
|
-
transition: {
|
|
121
|
-
duration: 0.5,
|
|
122
|
-
ease: [0.16, 1, 0.3, 1],
|
|
123
|
-
},
|
|
124
|
-
},
|
|
125
|
-
exit: { opacity: 0, y: -20 }
|
|
126
|
-
};
|
|
127
|
-
|
|
128
|
-
function AnimatedList({ items }) {
|
|
129
|
-
return (
|
|
130
|
-
<motion.ul
|
|
131
|
-
variants={containerVariants}
|
|
132
|
-
initial="hidden"
|
|
133
|
-
animate="visible"
|
|
134
|
-
exit="exit"
|
|
135
|
-
>
|
|
136
|
-
{items.map(item => (
|
|
137
|
-
<motion.li key={item.id} variants={itemVariants}>
|
|
138
|
-
{item.name}
|
|
139
|
-
</motion.li>
|
|
140
|
-
))}
|
|
141
|
-
</motion.ul>
|
|
142
|
-
);
|
|
143
|
-
}
|
|
144
|
-
```
|
|
145
|
-
|
|
146
|
-
### Variantes de stagger patterns
|
|
147
|
-
|
|
148
|
-
```tsx
|
|
149
|
-
// Stagger from center
|
|
150
|
-
const staggerFromCenter = {
|
|
151
|
-
visible: {
|
|
152
|
-
opacity: 1,
|
|
153
|
-
transition: {
|
|
154
|
-
staggerChildren: 0.08,
|
|
155
|
-
// Usando custom origin via index passado nas variants
|
|
156
|
-
},
|
|
157
|
-
},
|
|
158
|
-
};
|
|
159
|
-
|
|
160
|
-
// Stagger com velocidades diferentes por nivel
|
|
161
|
-
const parentVariants = {
|
|
162
|
-
visible: { transition: { staggerChildren: 0.1 } }
|
|
163
|
-
};
|
|
164
|
-
|
|
165
|
-
const childVariants = {
|
|
166
|
-
visible: { transition: { staggerChildren: 0.05 } }
|
|
167
|
-
};
|
|
168
|
-
```
|
|
169
|
-
|
|
170
|
-
---
|
|
171
|
-
|
|
172
|
-
## AnimatePresence — Animacoes de Saida
|
|
173
|
-
|
|
174
|
-
Sem `AnimatePresence`, animacoes de saida (exit) sao ignoradas. Ele monitora a arvore e permite que componentes se animem antes de ser removidos do DOM.
|
|
175
|
-
|
|
176
|
-
```tsx
|
|
177
|
-
import { AnimatePresence, motion } from 'framer-motion';
|
|
178
|
-
|
|
179
|
-
// Modal com entrada e saida animada
|
|
180
|
-
function Modal({ isOpen, onClose, children }) {
|
|
181
|
-
return (
|
|
182
|
-
<AnimatePresence>
|
|
183
|
-
{isOpen && (
|
|
184
|
-
<>
|
|
185
|
-
{/* Overlay */}
|
|
186
|
-
<motion.div
|
|
187
|
-
className="fixed inset-0 bg-black/50"
|
|
188
|
-
initial={{ opacity: 0 }}
|
|
189
|
-
animate={{ opacity: 1 }}
|
|
190
|
-
exit={{ opacity: 0 }}
|
|
191
|
-
onClick={onClose}
|
|
192
|
-
/>
|
|
193
|
-
|
|
194
|
-
{/* Modal */}
|
|
195
|
-
<motion.div
|
|
196
|
-
className="fixed inset-x-4 top-1/2 -translate-y-1/2 bg-white rounded-2xl p-6"
|
|
197
|
-
initial={{ opacity: 0, scale: 0.95, y: 20 }}
|
|
198
|
-
animate={{ opacity: 1, scale: 1, y: 0 }}
|
|
199
|
-
exit={{ opacity: 0, scale: 0.95, y: 20 }}
|
|
200
|
-
transition={{ type: 'spring', damping: 25, stiffness: 300 }}
|
|
201
|
-
>
|
|
202
|
-
{children}
|
|
203
|
-
</motion.div>
|
|
204
|
-
</>
|
|
205
|
-
)}
|
|
206
|
-
</AnimatePresence>
|
|
207
|
-
);
|
|
208
|
-
}
|
|
209
|
-
```
|
|
210
|
-
|
|
211
|
-
### mode prop do AnimatePresence
|
|
212
|
-
|
|
213
|
-
```tsx
|
|
214
|
-
// "sync" (default) — entrada e saida simultaneous
|
|
215
|
-
// "wait" — aguarda saida antes de iniciar entrada
|
|
216
|
-
// "popLayout" — remove elemento do layout durante animacao de saida
|
|
217
|
-
|
|
218
|
-
<AnimatePresence mode="wait">
|
|
219
|
-
{key && <motion.div key={key} />}
|
|
220
|
-
</AnimatePresence>
|
|
221
|
-
```
|
|
222
|
-
|
|
223
|
-
### Page transitions com Next.js
|
|
224
|
-
|
|
225
|
-
```tsx
|
|
226
|
-
// app/layout.tsx
|
|
227
|
-
'use client';
|
|
228
|
-
import { AnimatePresence, motion } from 'framer-motion';
|
|
229
|
-
import { usePathname } from 'next/navigation';
|
|
230
|
-
|
|
231
|
-
const pageVariants = {
|
|
232
|
-
initial: { opacity: 0, y: 20 },
|
|
233
|
-
in: { opacity: 1, y: 0 },
|
|
234
|
-
out: { opacity: 0, y: -20 },
|
|
235
|
-
};
|
|
236
|
-
|
|
237
|
-
const pageTransition = {
|
|
238
|
-
duration: 0.3,
|
|
239
|
-
ease: [0.16, 1, 0.3, 1],
|
|
240
|
-
};
|
|
241
|
-
|
|
242
|
-
export function PageTransitionLayout({ children }) {
|
|
243
|
-
const pathname = usePathname();
|
|
244
|
-
|
|
245
|
-
return (
|
|
246
|
-
<AnimatePresence mode="wait">
|
|
247
|
-
<motion.div
|
|
248
|
-
key={pathname}
|
|
249
|
-
variants={pageVariants}
|
|
250
|
-
initial="initial"
|
|
251
|
-
animate="in"
|
|
252
|
-
exit="out"
|
|
253
|
-
transition={pageTransition}
|
|
254
|
-
>
|
|
255
|
-
{children}
|
|
256
|
-
</motion.div>
|
|
257
|
-
</AnimatePresence>
|
|
258
|
-
);
|
|
259
|
-
}
|
|
260
|
-
```
|
|
261
|
-
|
|
262
|
-
---
|
|
263
|
-
|
|
264
|
-
## Layout Animations (FLIP)
|
|
265
|
-
|
|
266
|
-
`layout` prop ativa animacao automatica quando o layout muda — Framer Motion usa o algoritmo FLIP internamente para performance.
|
|
267
|
-
|
|
268
|
-
```tsx
|
|
269
|
-
// Reordenamento animado de lista
|
|
270
|
-
function SortableList({ items }) {
|
|
271
|
-
return (
|
|
272
|
-
<motion.ul layout>
|
|
273
|
-
{items.map(item => (
|
|
274
|
-
<motion.li
|
|
275
|
-
key={item.id}
|
|
276
|
-
layout // Anima mudancas de posicao
|
|
277
|
-
initial={{ opacity: 0, scale: 0.8 }}
|
|
278
|
-
animate={{ opacity: 1, scale: 1 }}
|
|
279
|
-
exit={{ opacity: 0, scale: 0.8 }}
|
|
280
|
-
transition={{ type: 'spring', stiffness: 300, damping: 25 }}
|
|
281
|
-
>
|
|
282
|
-
{item.name}
|
|
283
|
-
</motion.li>
|
|
284
|
-
))}
|
|
285
|
-
</motion.ul>
|
|
286
|
-
);
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
// Expandir/colapsar card com layout animation
|
|
290
|
-
function ExpandableCard({ title, content }) {
|
|
291
|
-
const [isExpanded, setIsExpanded] = useState(false);
|
|
292
|
-
|
|
293
|
-
return (
|
|
294
|
-
<motion.div
|
|
295
|
-
layout
|
|
296
|
-
className="card"
|
|
297
|
-
onClick={() => setIsExpanded(!isExpanded)}
|
|
298
|
-
>
|
|
299
|
-
<motion.h3 layout="position">{title}</motion.h3>
|
|
300
|
-
<AnimatePresence>
|
|
301
|
-
{isExpanded && (
|
|
302
|
-
<motion.p
|
|
303
|
-
initial={{ opacity: 0 }}
|
|
304
|
-
animate={{ opacity: 1 }}
|
|
305
|
-
exit={{ opacity: 0 }}
|
|
306
|
-
>
|
|
307
|
-
{content}
|
|
308
|
-
</motion.p>
|
|
309
|
-
)}
|
|
310
|
-
</AnimatePresence>
|
|
311
|
-
</motion.div>
|
|
312
|
-
);
|
|
313
|
-
}
|
|
314
|
-
```
|
|
315
|
-
|
|
316
|
-
### Shared Element Transitions (layoutId)
|
|
317
|
-
|
|
318
|
-
```tsx
|
|
319
|
-
// Galeria com elemento compartilhado entre estados
|
|
320
|
-
function Gallery({ images }) {
|
|
321
|
-
const [selectedId, setSelectedId] = useState(null);
|
|
322
|
-
|
|
323
|
-
return (
|
|
324
|
-
<>
|
|
325
|
-
{images.map(image => (
|
|
326
|
-
<motion.img
|
|
327
|
-
key={image.id}
|
|
328
|
-
layoutId={`image-${image.id}`} // ID unico para o par
|
|
329
|
-
src={image.src}
|
|
330
|
-
className="thumbnail"
|
|
331
|
-
onClick={() => setSelectedId(image.id)}
|
|
332
|
-
style={{ cursor: 'pointer' }}
|
|
333
|
-
/>
|
|
334
|
-
))}
|
|
335
|
-
|
|
336
|
-
<AnimatePresence>
|
|
337
|
-
{selectedId && (
|
|
338
|
-
<motion.div className="overlay" onClick={() => setSelectedId(null)}>
|
|
339
|
-
<motion.img
|
|
340
|
-
layoutId={`image-${selectedId}`} // Mesmo ID = elemento compartilhado
|
|
341
|
-
src={images.find(i => i.id === selectedId).src}
|
|
342
|
-
className="fullscreen"
|
|
343
|
-
/>
|
|
344
|
-
</motion.div>
|
|
345
|
-
)}
|
|
346
|
-
</AnimatePresence>
|
|
347
|
-
</>
|
|
348
|
-
);
|
|
349
|
-
}
|
|
350
|
-
```
|
|
351
|
-
|
|
352
|
-
---
|
|
353
|
-
|
|
354
|
-
## Gestures
|
|
355
|
-
|
|
356
|
-
```tsx
|
|
357
|
-
// Drag com constraints
|
|
358
|
-
function DraggableCard() {
|
|
359
|
-
const constraintsRef = useRef(null);
|
|
360
|
-
|
|
361
|
-
return (
|
|
362
|
-
<div ref={constraintsRef} className="drag-area">
|
|
363
|
-
<motion.div
|
|
364
|
-
drag // Drag em ambas as direcoes
|
|
365
|
-
dragConstraints={constraintsRef} // Limitar ao container
|
|
366
|
-
dragElastic={0.1} // Elasticidade ao bater nos limites
|
|
367
|
-
dragMomentum={true} // Momentum apos soltar
|
|
368
|
-
whileDrag={{ scale: 1.1, rotate: 5 }}
|
|
369
|
-
onDragEnd={(event, info) => {
|
|
370
|
-
console.log(info.offset.x, info.velocity.x);
|
|
371
|
-
}}
|
|
372
|
-
>
|
|
373
|
-
Drag me
|
|
374
|
-
</motion.div>
|
|
375
|
-
</div>
|
|
376
|
-
);
|
|
377
|
-
}
|
|
378
|
-
|
|
379
|
-
// Swipe para dispensar (mobile pattern)
|
|
380
|
-
function SwipeToDismiss({ onDismiss, children }) {
|
|
381
|
-
return (
|
|
382
|
-
<motion.div
|
|
383
|
-
drag="x"
|
|
384
|
-
dragConstraints={{ left: 0, right: 0 }}
|
|
385
|
-
dragElastic={1}
|
|
386
|
-
onDragEnd={(_, info) => {
|
|
387
|
-
if (Math.abs(info.offset.x) > 100) onDismiss();
|
|
388
|
-
}}
|
|
389
|
-
animate={{ x: 0 }}
|
|
390
|
-
>
|
|
391
|
-
{children}
|
|
392
|
-
</motion.div>
|
|
393
|
-
);
|
|
394
|
-
}
|
|
395
|
-
|
|
396
|
-
// Hover + tap combinados
|
|
397
|
-
function InteractiveCard() {
|
|
398
|
-
return (
|
|
399
|
-
<motion.div
|
|
400
|
-
whileHover={{ y: -8, scale: 1.02 }}
|
|
401
|
-
whileTap={{ scale: 0.98 }}
|
|
402
|
-
transition={{ type: 'spring', stiffness: 400, damping: 17 }}
|
|
403
|
-
style={{ cursor: 'pointer' }}
|
|
404
|
-
>
|
|
405
|
-
Card content
|
|
406
|
-
</motion.div>
|
|
407
|
-
);
|
|
408
|
-
}
|
|
409
|
-
```
|
|
410
|
-
|
|
411
|
-
---
|
|
412
|
-
|
|
413
|
-
## useAnimation — Controle Imperativo
|
|
414
|
-
|
|
415
|
-
```tsx
|
|
416
|
-
import { useAnimation } from 'framer-motion';
|
|
417
|
-
|
|
418
|
-
function ControlledAnimation() {
|
|
419
|
-
const controls = useAnimation();
|
|
420
|
-
|
|
421
|
-
const sequence = async () => {
|
|
422
|
-
await controls.start({ x: 100, transition: { duration: 0.3 } });
|
|
423
|
-
await controls.start({ y: 100, transition: { duration: 0.3 } });
|
|
424
|
-
await controls.start({ x: 0, y: 0, transition: { duration: 0.5 } });
|
|
425
|
-
};
|
|
426
|
-
|
|
427
|
-
return (
|
|
428
|
-
<>
|
|
429
|
-
<motion.div animate={controls} />
|
|
430
|
-
<button onClick={sequence}>Start sequence</button>
|
|
431
|
-
</>
|
|
432
|
-
);
|
|
433
|
-
}
|
|
434
|
-
```
|
|
435
|
-
|
|
436
|
-
---
|
|
437
|
-
|
|
438
|
-
## useMotionValue + useTransform — Motion Values Reativas
|
|
439
|
-
|
|
440
|
-
```tsx
|
|
441
|
-
import { motion, useMotionValue, useTransform, useSpring } from 'framer-motion';
|
|
442
|
-
|
|
443
|
-
function TiltCard() {
|
|
444
|
-
const x = useMotionValue(0);
|
|
445
|
-
const y = useMotionValue(0);
|
|
446
|
-
|
|
447
|
-
// Transformar posicao do mouse em rotacao
|
|
448
|
-
const rotateX = useTransform(y, [-100, 100], [15, -15]);
|
|
449
|
-
const rotateY = useTransform(x, [-100, 100], [-15, 15]);
|
|
450
|
-
|
|
451
|
-
// Adicionar spring para suavizar
|
|
452
|
-
const springConfig = { stiffness: 150, damping: 20 };
|
|
453
|
-
const smoothRotateX = useSpring(rotateX, springConfig);
|
|
454
|
-
const smoothRotateY = useSpring(rotateY, springConfig);
|
|
455
|
-
|
|
456
|
-
function handleMouseMove(e) {
|
|
457
|
-
const rect = e.currentTarget.getBoundingClientRect();
|
|
458
|
-
x.set(e.clientX - rect.left - rect.width / 2);
|
|
459
|
-
y.set(e.clientY - rect.top - rect.height / 2);
|
|
460
|
-
}
|
|
461
|
-
|
|
462
|
-
function handleMouseLeave() {
|
|
463
|
-
x.set(0);
|
|
464
|
-
y.set(0);
|
|
465
|
-
}
|
|
466
|
-
|
|
467
|
-
return (
|
|
468
|
-
<motion.div
|
|
469
|
-
onMouseMove={handleMouseMove}
|
|
470
|
-
onMouseLeave={handleMouseLeave}
|
|
471
|
-
style={{ rotateX: smoothRotateX, rotateY: smoothRotateY, perspective: 1000 }}
|
|
472
|
-
>
|
|
473
|
-
Tilt card content
|
|
474
|
-
</motion.div>
|
|
475
|
-
);
|
|
476
|
-
}
|
|
477
|
-
|
|
478
|
-
// Scroll progress indicator
|
|
479
|
-
import { useScroll } from 'framer-motion';
|
|
480
|
-
|
|
481
|
-
function ScrollProgress() {
|
|
482
|
-
const { scrollYProgress } = useScroll();
|
|
483
|
-
const scaleX = useSpring(scrollYProgress, { stiffness: 100, damping: 30 });
|
|
484
|
-
|
|
485
|
-
return (
|
|
486
|
-
<motion.div
|
|
487
|
-
className="fixed top-0 left-0 right-0 h-1 bg-blue-500"
|
|
488
|
-
style={{ scaleX, transformOrigin: '0%' }}
|
|
489
|
-
/>
|
|
490
|
-
);
|
|
491
|
-
}
|
|
492
|
-
```
|
|
493
|
-
|
|
494
|
-
---
|
|
495
|
-
|
|
496
|
-
## whileInView — Scroll Reveals
|
|
497
|
-
|
|
498
|
-
```tsx
|
|
499
|
-
// Reveal simples com viewport
|
|
500
|
-
function ScrollReveal({ children }) {
|
|
501
|
-
return (
|
|
502
|
-
<motion.div
|
|
503
|
-
initial={{ opacity: 0, y: 50 }}
|
|
504
|
-
whileInView={{ opacity: 1, y: 0 }}
|
|
505
|
-
viewport={{
|
|
506
|
-
once: true, // Anima apenas uma vez
|
|
507
|
-
margin: '-100px', // Triggeriza 100px antes de entrar
|
|
508
|
-
amount: 0.3, // 30% visivel para triggerizar
|
|
509
|
-
}}
|
|
510
|
-
transition={{ duration: 0.6, ease: [0.16, 1, 0.3, 1] }}
|
|
511
|
-
>
|
|
512
|
-
{children}
|
|
513
|
-
</motion.div>
|
|
514
|
-
);
|
|
515
|
-
}
|
|
516
|
-
|
|
517
|
-
// Reveal de texto caractere a caractere
|
|
518
|
-
function TextReveal({ text }) {
|
|
519
|
-
return (
|
|
520
|
-
<motion.span>
|
|
521
|
-
{text.split('').map((char, i) => (
|
|
522
|
-
<motion.span
|
|
523
|
-
key={i}
|
|
524
|
-
initial={{ opacity: 0, y: 20 }}
|
|
525
|
-
whileInView={{ opacity: 1, y: 0 }}
|
|
526
|
-
viewport={{ once: true }}
|
|
527
|
-
transition={{ delay: i * 0.03, duration: 0.4 }}
|
|
528
|
-
style={{ display: 'inline-block' }}
|
|
529
|
-
>
|
|
530
|
-
{char === ' ' ? '\u00A0' : char}
|
|
531
|
-
</motion.span>
|
|
532
|
-
))}
|
|
533
|
-
</motion.span>
|
|
534
|
-
);
|
|
535
|
-
}
|
|
536
|
-
```
|
|
537
|
-
|
|
538
|
-
---
|
|
539
|
-
|
|
540
|
-
## Spring Physics — Referencia Rapida
|
|
541
|
-
|
|
542
|
-
```tsx
|
|
543
|
-
// Presets de spring para situacoes comuns
|
|
544
|
-
const springs = {
|
|
545
|
-
snappy: { type: 'spring', stiffness: 400, damping: 30 }, // Botoes, inputs
|
|
546
|
-
gentle: { type: 'spring', stiffness: 100, damping: 15 }, // Cards, panels
|
|
547
|
-
bouncy: { type: 'spring', stiffness: 200, damping: 10 }, // Notificacoes, badges
|
|
548
|
-
heavy: { type: 'spring', stiffness: 200, damping: 25, mass: 3 }, // Drawers, modais grandes
|
|
549
|
-
wobbly: { type: 'spring', stiffness: 150, damping: 8 }, // Playful, games
|
|
550
|
-
};
|
|
551
|
-
|
|
552
|
-
// Uso
|
|
553
|
-
<motion.div transition={springs.snappy} whileTap={{ scale: 0.95 }} />
|
|
554
|
-
```
|
|
555
|
-
|
|
556
|
-
---
|
|
557
|
-
|
|
558
|
-
## SVG Morphing com Framer Motion
|
|
559
|
-
|
|
560
|
-
```tsx
|
|
561
|
-
// Toggle icon (hamburger -> X)
|
|
562
|
-
function MenuIcon({ isOpen }) {
|
|
563
|
-
return (
|
|
564
|
-
<svg viewBox="0 0 24 24" width={24} height={24}>
|
|
565
|
-
<motion.path
|
|
566
|
-
fill="none"
|
|
567
|
-
stroke="currentColor"
|
|
568
|
-
strokeWidth={2}
|
|
569
|
-
strokeLinecap="round"
|
|
570
|
-
animate={{
|
|
571
|
-
d: isOpen
|
|
572
|
-
? 'M6 18L18 6M6 6l12 12' // X icon
|
|
573
|
-
: 'M4 6h16M4 12h16M4 18h16' // Hamburger
|
|
574
|
-
}}
|
|
575
|
-
transition={{ duration: 0.3, ease: [0.16, 1, 0.3, 1] }}
|
|
576
|
-
/>
|
|
577
|
-
</svg>
|
|
578
|
-
);
|
|
579
|
-
}
|
|
580
|
-
|
|
581
|
-
// Progresso circular animado
|
|
582
|
-
function CircularProgress({ progress }) {
|
|
583
|
-
const circumference = 2 * Math.PI * 45; // raio 45
|
|
584
|
-
const strokeDashoffset = circumference * (1 - progress);
|
|
585
|
-
|
|
586
|
-
return (
|
|
587
|
-
<svg viewBox="0 0 100 100" width={100} height={100}>
|
|
588
|
-
<circle cx="50" cy="50" r="45" fill="none" stroke="#eee" strokeWidth="8" />
|
|
589
|
-
<motion.circle
|
|
590
|
-
cx="50" cy="50" r="45"
|
|
591
|
-
fill="none"
|
|
592
|
-
stroke="#0066ff"
|
|
593
|
-
strokeWidth="8"
|
|
594
|
-
strokeLinecap="round"
|
|
595
|
-
strokeDasharray={circumference}
|
|
596
|
-
animate={{ strokeDashoffset }}
|
|
597
|
-
transition={{ duration: 0.5, ease: 'easeOut' }}
|
|
598
|
-
style={{ rotate: -90, transformOrigin: 'center' }}
|
|
599
|
-
/>
|
|
600
|
-
</svg>
|
|
601
|
-
);
|
|
602
|
-
}
|
|
603
|
-
```
|
|
604
|
-
|
|
605
|
-
---
|
|
606
|
-
|
|
607
|
-
## Patterns Avancados
|
|
608
|
-
|
|
609
|
-
### Botao com ripple effect
|
|
610
|
-
|
|
611
|
-
```tsx
|
|
612
|
-
function RippleButton({ children, onClick }) {
|
|
613
|
-
return (
|
|
614
|
-
<motion.button
|
|
615
|
-
whileHover={{ scale: 1.02, y: -2 }}
|
|
616
|
-
whileTap={{ scale: 0.98 }}
|
|
617
|
-
transition={springs.snappy}
|
|
618
|
-
onClick={onClick}
|
|
619
|
-
className="relative overflow-hidden"
|
|
620
|
-
>
|
|
621
|
-
{children}
|
|
622
|
-
<motion.span
|
|
623
|
-
className="absolute inset-0 bg-white/20 rounded-full"
|
|
624
|
-
initial={{ scale: 0, opacity: 1 }}
|
|
625
|
-
whileTap={{ scale: 4, opacity: 0 }}
|
|
626
|
-
transition={{ duration: 0.6 }}
|
|
627
|
-
/>
|
|
628
|
-
</motion.button>
|
|
629
|
-
);
|
|
630
|
-
}
|
|
631
|
-
```
|
|
632
|
-
|
|
633
|
-
### Loading skeleton com shimmer
|
|
634
|
-
|
|
635
|
-
```tsx
|
|
636
|
-
function Skeleton({ className }) {
|
|
637
|
-
return (
|
|
638
|
-
<motion.div
|
|
639
|
-
className={`rounded-md bg-gray-200 overflow-hidden ${className}`}
|
|
640
|
-
animate={{ opacity: [0.5, 1, 0.5] }}
|
|
641
|
-
transition={{ duration: 1.5, repeat: Infinity, ease: 'easeInOut' }}
|
|
642
|
-
/>
|
|
643
|
-
);
|
|
644
|
-
}
|
|
645
|
-
```
|
|
646
|
-
|
|
647
|
-
### Counter animado
|
|
648
|
-
|
|
649
|
-
```tsx
|
|
650
|
-
import { useMotionValue, useSpring, useEffect } from 'framer-motion';
|
|
651
|
-
|
|
652
|
-
function AnimatedCounter({ to, duration = 2 }) {
|
|
653
|
-
const count = useMotionValue(0);
|
|
654
|
-
const rounded = useTransform(count, Math.round);
|
|
655
|
-
const spring = useSpring(count, { duration: duration * 1000 });
|
|
656
|
-
|
|
657
|
-
useEffect(() => {
|
|
658
|
-
spring.set(to);
|
|
659
|
-
}, [to]);
|
|
660
|
-
|
|
661
|
-
return <motion.span>{rounded}</motion.span>;
|
|
662
|
-
}
|
|
663
|
-
```
|
|
664
|
-
|
|
665
|
-
---
|
|
666
|
-
|
|
667
|
-
## Acessibilidade
|
|
668
|
-
|
|
669
|
-
```tsx
|
|
670
|
-
// prefers-reduced-motion
|
|
671
|
-
import { useReducedMotion } from 'framer-motion';
|
|
672
|
-
|
|
673
|
-
function AccessibleAnimation({ children }) {
|
|
674
|
-
const shouldReduceMotion = useReducedMotion();
|
|
675
|
-
|
|
676
|
-
return (
|
|
677
|
-
<motion.div
|
|
678
|
-
initial={{ opacity: 0, y: shouldReduceMotion ? 0 : 30 }}
|
|
679
|
-
animate={{ opacity: 1, y: 0 }}
|
|
680
|
-
transition={{ duration: shouldReduceMotion ? 0.01 : 0.5 }}
|
|
681
|
-
>
|
|
682
|
-
{children}
|
|
683
|
-
</motion.div>
|
|
684
|
-
);
|
|
685
|
-
}
|
|
686
|
-
|
|
687
|
-
// Hook personalizado para aplicar em toda a app
|
|
688
|
-
function useMotionSafe() {
|
|
689
|
-
const shouldReduceMotion = useReducedMotion();
|
|
690
|
-
|
|
691
|
-
return {
|
|
692
|
-
transition: shouldReduceMotion
|
|
693
|
-
? { duration: 0.01 }
|
|
694
|
-
: { duration: 0.5, ease: [0.16, 1, 0.3, 1] },
|
|
695
|
-
initial: shouldReduceMotion ? {} : { opacity: 0, y: 20 },
|
|
696
|
-
animate: { opacity: 1, y: 0 },
|
|
697
|
-
};
|
|
698
|
-
}
|
|
699
|
-
```
|
|
700
|
-
|
|
701
|
-
---
|
|
702
|
-
|
|
703
|
-
## Performance Tips
|
|
704
|
-
|
|
705
|
-
1. **Evitar animar `width`/`height`** — usar `scaleX`/`scaleY` + `transformOrigin`
|
|
706
|
-
2. **`layout` prop e pesada** — usar apenas quando necessario (FLIP tem custo)
|
|
707
|
-
3. **`LazyMotion`** — carregar features sob demanda para menor bundle
|
|
708
|
-
4. **`will-change`** — Framer Motion ja aplica automaticamente quando necessario
|
|
709
|
-
5. **Evitar re-renders** — `useMotionValue` nao triggeriza re-render (diferente de `useState`)
|
|
710
|
-
6. **`frameloop="demand"`** em Canvas R3F quando integrado com Framer Motion
|