@zoyth/simple-site-framework 1.0.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/LICENSE +21 -0
- package/README.md +572 -0
- package/bin/create-simple-site.js +390 -0
- package/bin/simple-site.js +664 -0
- package/dist/client.js +135 -0
- package/dist/client.js.map +1 -0
- package/dist/client.mjs +107 -0
- package/dist/client.mjs.map +1 -0
- package/dist/components/index.d.mts +3936 -0
- package/dist/components/index.d.ts +3936 -0
- package/dist/components/index.js +38265 -0
- package/dist/components/index.js.map +1 -0
- package/dist/components/index.mjs +38173 -0
- package/dist/components/index.mjs.map +1 -0
- package/dist/config/index.d.mts +298 -0
- package/dist/config/index.d.ts +298 -0
- package/dist/config/index.js +19 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/index.mjs +1 -0
- package/dist/config/index.mjs.map +1 -0
- package/dist/index.d.mts +2184 -0
- package/dist/index.d.ts +2184 -0
- package/dist/index.js +1713 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +1605 -0
- package/dist/index.mjs.map +1 -0
- package/dist/lib/i18n/index.js +665 -0
- package/dist/lib/i18n/index.js.map +1 -0
- package/dist/lib/i18n/index.mjs +621 -0
- package/dist/lib/i18n/index.mjs.map +1 -0
- package/docs/DOCUMENTATION-STRUCTURE.md +1156 -0
- package/docs/EXPORTS.md +125 -0
- package/docs/PERFORMANCE.md +757 -0
- package/docs/POLICY-PAGES.md +867 -0
- package/docs/ROADMAP.md +334 -0
- package/docs/SEO.md +455 -0
- package/docs/SITEMAP.md +708 -0
- package/docs/STRUCTURED-DATA.md +671 -0
- package/docs/accessibility/common-patterns.md +529 -0
- package/docs/accessibility/keyboard-navigation.md +263 -0
- package/docs/accessibility/overview.md +122 -0
- package/docs/accessibility/screen-readers.md +311 -0
- package/docs/accessibility/wcag-compliance.md +159 -0
- package/docs/api/README.md +164 -0
- package/docs/api/components/Accessibility.md +356 -0
- package/docs/api/components/Button.md +240 -0
- package/docs/api/components/HeroSection.md +306 -0
- package/docs/architecture/decisions.md +449 -0
- package/docs/components/AnalyticsTracker.md +58 -0
- package/docs/components/AnimatedCounter.md +48 -0
- package/docs/components/AnimatedSection.md +56 -0
- package/docs/components/BlogCard.md +42 -0
- package/docs/components/Checkbox.md +56 -0
- package/docs/components/CodeBlock.md +52 -0
- package/docs/components/ComparisonTable.md +40 -0
- package/docs/components/ComponentDemo.md +38 -0
- package/docs/components/CountdownTimer.md +51 -0
- package/docs/components/ExitIntentModal.md +56 -0
- package/docs/components/FAQAccordion.md +66 -0
- package/docs/components/FeaturesGrid.md +55 -0
- package/docs/components/FileUpload.md +54 -0
- package/docs/components/I18nMetaTags.md +55 -0
- package/docs/components/Icon.md +53 -0
- package/docs/components/LazySection.md +46 -0
- package/docs/components/LiveProof.md +53 -0
- package/docs/components/LoadingSpinner.md +46 -0
- package/docs/components/MultiStepForm.md +48 -0
- package/docs/components/PolicyLayout.md +55 -0
- package/docs/components/PricingTable.md +49 -0
- package/docs/components/Radio.md +59 -0
- package/docs/components/SEOMetaTags.md +58 -0
- package/docs/components/ScriptInjector.md +50 -0
- package/docs/components/Select.md +72 -0
- package/docs/components/Skeleton.md +47 -0
- package/docs/components/StatsSection.md +48 -0
- package/docs/components/StickyBar.md +62 -0
- package/docs/components/StructuredData.md +99 -0
- package/docs/components/StyleGuide.md +46 -0
- package/docs/components/TableOfContents.md +47 -0
- package/docs/components/TestimonialCarousel.md +42 -0
- package/docs/components/Timeline.md +51 -0
- package/docs/components/Toast.md +59 -0
- package/docs/components/TrackedLink.md +62 -0
- package/docs/components/TrustBadges.md +44 -0
- package/docs/components/conversion/MobileCTA.md +363 -0
- package/docs/components/forms/ContactForm.md +75 -0
- package/docs/components/forms/FormField.md +74 -0
- package/docs/components/layout/Footer.md +601 -0
- package/docs/components/layout/Header.md +549 -0
- package/docs/components/layout/LanguageSelector.md +54 -0
- package/docs/components/layout/LanguageSwitcher.md +24 -0
- package/docs/components/overview.md +447 -0
- package/docs/components/sections/AboutSection.md +48 -0
- package/docs/components/sections/CTASection.md +596 -0
- package/docs/components/sections/CaseStudySection.md +47 -0
- package/docs/components/sections/ContactSection.md +599 -0
- package/docs/components/sections/FeatureSection.md +44 -0
- package/docs/components/sections/HeroSection.md +404 -0
- package/docs/components/sections/LogosSection.md +47 -0
- package/docs/components/sections/PersonalTaxesSection.md +23 -0
- package/docs/components/sections/RecruitingSection.md +23 -0
- package/docs/components/sections/SecurePortalSection.md +23 -0
- package/docs/components/sections/ServicePageLayout.md +52 -0
- package/docs/components/sections/ServicesSection.md +49 -0
- package/docs/components/sections/TestimonialSection.md +44 -0
- package/docs/components/sections/WhyChooseUsSection.md +54 -0
- package/docs/components/ui/Breadcrumb.md +70 -0
- package/docs/components/ui/Button.md +514 -0
- package/docs/components/ui/Card.md +501 -0
- package/docs/components/ui/Input.md +54 -0
- package/docs/components/ui/MobileLinks.md +43 -0
- package/docs/components/ui/Modal.md +60 -0
- package/docs/components/ui/Tabs.md +62 -0
- package/docs/components/ui/Textarea.md +52 -0
- package/docs/core-concepts/configuration-driven.md +552 -0
- package/docs/core-concepts/overview.md +351 -0
- package/docs/features/accessibility/README.md +73 -0
- package/docs/features/accessibility/aria-support.md +177 -0
- package/docs/features/accessibility/color-contrast.md +155 -0
- package/docs/features/accessibility/focus-management.md +187 -0
- package/docs/features/accessibility/testing.md +196 -0
- package/docs/features/analytics/README.md +51 -0
- package/docs/features/analytics/ab-testing.md +171 -0
- package/docs/features/analytics/conversion-tracking.md +207 -0
- package/docs/features/analytics/custom-events.md +219 -0
- package/docs/features/analytics/privacy.md +198 -0
- package/docs/features/analytics/setup.md +114 -0
- package/docs/features/analytics/tracking-events.md +224 -0
- package/docs/features/i18n/README.md +51 -0
- package/docs/features/i18n/best-practices.md +273 -0
- package/docs/features/i18n/configuration.md +84 -0
- package/docs/features/i18n/formatting.md +133 -0
- package/docs/features/i18n/locale-detection.md +122 -0
- package/docs/features/i18n/routing.md +99 -0
- package/docs/features/i18n/rtl-support.md +191 -0
- package/docs/features/i18n/translations.md +129 -0
- package/docs/features/internationalization.md +595 -0
- package/docs/features/performance/README.md +77 -0
- package/docs/features/performance/bundle-size.md +134 -0
- package/docs/features/performance/caching.md +131 -0
- package/docs/features/performance/code-splitting.md +121 -0
- package/docs/features/performance/image-optimization.md +110 -0
- package/docs/features/performance/lazy-loading.md +92 -0
- package/docs/features/performance/monitoring.md +148 -0
- package/docs/features/seo/README.md +51 -0
- package/docs/features/seo/best-practices.md +184 -0
- package/docs/features/seo/canonical-urls.md +182 -0
- package/docs/features/seo/meta-tags.md +126 -0
- package/docs/features/seo/open-graph.md +166 -0
- package/docs/features/seo/robots-txt.md +146 -0
- package/docs/features/seo/sitemaps.md +162 -0
- package/docs/features/seo/structured-data.md +166 -0
- package/docs/getting-started/installation.md +292 -0
- package/docs/getting-started/introduction.md +195 -0
- package/docs/getting-started/quick-start.md +460 -0
- package/docs/guides/analytics-setup.md +616 -0
- package/docs/i18n/CONFIGURATION.md +353 -0
- package/docs/i18n/EXAMPLES.md +402 -0
- package/docs/i18n/MIGRATION.md +260 -0
- package/docs/i18n/SEO.md +392 -0
- package/docs/i18n/STATIC-GENERATION-FIX.md +71 -0
- package/docs/migration/changelog.md +136 -0
- package/docs/migration/overview.md +233 -0
- package/docs/recipes/adding-animations.md +475 -0
- package/docs/recipes/forms-with-validation.md +393 -0
- package/package.json +152 -0
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
# Migration Guide Overview
|
|
2
|
+
|
|
3
|
+
This guide helps you upgrade between versions of the Simple Site Framework smoothly.
|
|
4
|
+
|
|
5
|
+
## Version Support Policy
|
|
6
|
+
|
|
7
|
+
### Current Versions
|
|
8
|
+
- **v0.1.x**: Initial release, active development
|
|
9
|
+
- Future versions will follow semantic versioning
|
|
10
|
+
|
|
11
|
+
### Support Timeline
|
|
12
|
+
- **Major versions** (v1.x, v2.x): 18 months of support
|
|
13
|
+
- **Minor versions** (v0.1.x, v0.2.x): Supported until next minor release
|
|
14
|
+
- **Patch versions** (v0.1.0, v0.1.1): Immediate upgrade recommended
|
|
15
|
+
|
|
16
|
+
### Long-Term Support (LTS)
|
|
17
|
+
Starting with v1.0, LTS versions will be designated:
|
|
18
|
+
- Security fixes for 18 months
|
|
19
|
+
- Bug fixes for 12 months
|
|
20
|
+
- New features for 6 months
|
|
21
|
+
|
|
22
|
+
## Semantic Versioning
|
|
23
|
+
|
|
24
|
+
We follow [Semantic Versioning 2.0.0](https://semver.org/):
|
|
25
|
+
|
|
26
|
+
- **Major** (v1.0.0 → v2.0.0): Breaking changes
|
|
27
|
+
- **Minor** (v0.1.0 → v0.2.0): New features, backward compatible
|
|
28
|
+
- **Patch** (v0.1.0 → v0.1.1): Bug fixes, backward compatible
|
|
29
|
+
|
|
30
|
+
## Before You Upgrade
|
|
31
|
+
|
|
32
|
+
### 1. Check Current Version
|
|
33
|
+
```bash
|
|
34
|
+
npm list @zoyth/simple-site-framework
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### 2. Review Breaking Changes
|
|
38
|
+
Read the migration guide for your target version:
|
|
39
|
+
- [v0.1 → v0.2](./v0.1-to-v0.2.md) (when available)
|
|
40
|
+
- [Changelog](./changelog.md)
|
|
41
|
+
|
|
42
|
+
### 3. Backup Your Code
|
|
43
|
+
```bash
|
|
44
|
+
git commit -am "Pre-upgrade checkpoint"
|
|
45
|
+
git tag pre-upgrade-v0.2
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### 4. Update Dependencies
|
|
49
|
+
```bash
|
|
50
|
+
npm install @zoyth/simple-site-framework@latest
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### 5. Run Migration Tool (Optional)
|
|
54
|
+
```bash
|
|
55
|
+
npx simple-site migrate
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### 6. Test Thoroughly
|
|
59
|
+
- Run your test suite
|
|
60
|
+
- Manual QA on key pages
|
|
61
|
+
- Check for deprecation warnings
|
|
62
|
+
|
|
63
|
+
## Migration Tools
|
|
64
|
+
|
|
65
|
+
### Automated Migration
|
|
66
|
+
The framework includes automated migration tools to help with common upgrade scenarios:
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
# Interactive migration
|
|
70
|
+
npx simple-site migrate
|
|
71
|
+
|
|
72
|
+
# Dry run (see what would change)
|
|
73
|
+
npx simple-site migrate --dry-run
|
|
74
|
+
|
|
75
|
+
# Migrate to specific version
|
|
76
|
+
npx simple-site migrate --to=0.2.0
|
|
77
|
+
|
|
78
|
+
# Skip interactive prompts
|
|
79
|
+
npx simple-site migrate --yes
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### What Gets Migrated
|
|
83
|
+
- ✅ Component imports
|
|
84
|
+
- ✅ Prop names and values
|
|
85
|
+
- ✅ Config file structure
|
|
86
|
+
- ✅ Deprecated API usage
|
|
87
|
+
- ⚠️ Custom code (manual review needed)
|
|
88
|
+
|
|
89
|
+
## Deprecation Policy
|
|
90
|
+
|
|
91
|
+
### Deprecation Process
|
|
92
|
+
1. **Announce**: Deprecation warning added in minor version
|
|
93
|
+
2. **Maintain**: Deprecated feature still works for one major version
|
|
94
|
+
3. **Remove**: Feature removed in next major version
|
|
95
|
+
|
|
96
|
+
### Example Timeline
|
|
97
|
+
- v0.5: Feature deprecated, warning shown
|
|
98
|
+
- v0.6-0.9: Feature still works, warning continues
|
|
99
|
+
- v1.0: Feature removed
|
|
100
|
+
|
|
101
|
+
### Handling Deprecations
|
|
102
|
+
```tsx
|
|
103
|
+
// Deprecated in v0.5 - warning in console
|
|
104
|
+
<Button type="primary">Click</Button>
|
|
105
|
+
|
|
106
|
+
// New API (works in v0.5+)
|
|
107
|
+
<Button variant="filled">Click</Button>
|
|
108
|
+
|
|
109
|
+
// Both work in v0.5-0.9
|
|
110
|
+
// Only new API works in v1.0+
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
## Breaking Changes
|
|
114
|
+
|
|
115
|
+
Breaking changes are **only** introduced in major versions. Minor and patch versions are always backward compatible.
|
|
116
|
+
|
|
117
|
+
### Types of Breaking Changes
|
|
118
|
+
- Removed features
|
|
119
|
+
- Changed default behavior
|
|
120
|
+
- Required new dependencies
|
|
121
|
+
- Config structure changes
|
|
122
|
+
- Renamed components/props
|
|
123
|
+
- Changed TypeScript types
|
|
124
|
+
|
|
125
|
+
### How We Communicate Breaks
|
|
126
|
+
1. **Migration guide**: Detailed upgrade instructions
|
|
127
|
+
2. **Changelog**: Summary of all changes
|
|
128
|
+
3. **Release notes**: Highlights and recommendations
|
|
129
|
+
4. **Deprecation warnings**: In-app notifications before removal
|
|
130
|
+
|
|
131
|
+
## Getting Help
|
|
132
|
+
|
|
133
|
+
### Documentation
|
|
134
|
+
- [Migration Guides](./overview.md)
|
|
135
|
+
- [Changelog](./changelog.md)
|
|
136
|
+
- [GitHub Releases](https://github.com/zoyth/simple-site-framework/releases)
|
|
137
|
+
|
|
138
|
+
### Support
|
|
139
|
+
- **Issues**: [GitHub Issues](https://github.com/zoyth/simple-site-framework/issues)
|
|
140
|
+
- **Discussions**: [GitHub Discussions](https://github.com/zoyth/simple-site-framework/discussions)
|
|
141
|
+
- **Community**: Check for community posts about similar upgrades
|
|
142
|
+
|
|
143
|
+
### Before Filing an Issue
|
|
144
|
+
1. Read the migration guide
|
|
145
|
+
2. Check existing issues
|
|
146
|
+
3. Run `npx simple-site migrate`
|
|
147
|
+
4. Include version numbers and error messages
|
|
148
|
+
|
|
149
|
+
## Migration Checklist
|
|
150
|
+
|
|
151
|
+
Use this checklist for every upgrade:
|
|
152
|
+
|
|
153
|
+
- [ ] Read migration guide for target version
|
|
154
|
+
- [ ] Review changelog
|
|
155
|
+
- [ ] Backup code (git commit + tag)
|
|
156
|
+
- [ ] Update package.json
|
|
157
|
+
- [ ] Run `npm install`
|
|
158
|
+
- [ ] Run `npx simple-site migrate` (if available)
|
|
159
|
+
- [ ] Fix TypeScript errors
|
|
160
|
+
- [ ] Fix deprecation warnings
|
|
161
|
+
- [ ] Run test suite
|
|
162
|
+
- [ ] Manual QA testing
|
|
163
|
+
- [ ] Check for console warnings
|
|
164
|
+
- [ ] Review bundle size impact
|
|
165
|
+
- [ ] Update documentation
|
|
166
|
+
- [ ] Deploy to staging
|
|
167
|
+
- [ ] Monitor for issues
|
|
168
|
+
|
|
169
|
+
## Rollback Plan
|
|
170
|
+
|
|
171
|
+
If upgrade causes issues:
|
|
172
|
+
|
|
173
|
+
### Quick Rollback
|
|
174
|
+
```bash
|
|
175
|
+
# Revert to previous version
|
|
176
|
+
git reset --hard pre-upgrade-v0.2
|
|
177
|
+
npm install
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
### Gradual Upgrade
|
|
181
|
+
If full upgrade is risky:
|
|
182
|
+
|
|
183
|
+
1. **Create feature branch**
|
|
184
|
+
```bash
|
|
185
|
+
git checkout -b upgrade-v0.2
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
2. **Upgrade in stages**
|
|
189
|
+
- Update framework
|
|
190
|
+
- Migrate one route/feature at a time
|
|
191
|
+
- Test between each migration
|
|
192
|
+
|
|
193
|
+
3. **Merge when stable**
|
|
194
|
+
```bash
|
|
195
|
+
git checkout main
|
|
196
|
+
git merge upgrade-v0.2
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
## Version-Specific Guides
|
|
200
|
+
|
|
201
|
+
- [v0.1 → v0.2](./v0.1-to-v0.2.md) (example, create when needed)
|
|
202
|
+
- [Changelog](./changelog.md)
|
|
203
|
+
|
|
204
|
+
## Best Practices
|
|
205
|
+
|
|
206
|
+
1. **Upgrade regularly** - Don't fall too far behind
|
|
207
|
+
2. **Read release notes** - Stay informed about changes
|
|
208
|
+
3. **Test in staging first** - Never upgrade production directly
|
|
209
|
+
4. **Use lock files** - Commit package-lock.json
|
|
210
|
+
5. **Monitor deprecations** - Fix warnings before they break
|
|
211
|
+
6. **Keep dependencies updated** - Framework peer dependencies too
|
|
212
|
+
7. **Automated tests** - Catch regressions early
|
|
213
|
+
8. **Document custom code** - Note why you did something unconventional
|
|
214
|
+
|
|
215
|
+
## FAQ
|
|
216
|
+
|
|
217
|
+
**Q: Can I skip versions?**
|
|
218
|
+
A: Yes, but read all intermediate migration guides. Run `npx simple-site migrate` to handle multiple version jumps.
|
|
219
|
+
|
|
220
|
+
**Q: Will my site break on upgrade?**
|
|
221
|
+
A: Minor/patch upgrades are backward compatible. Major upgrades may have breaking changes, but migration tools help.
|
|
222
|
+
|
|
223
|
+
**Q: How long are versions supported?**
|
|
224
|
+
A: See [Version Support Policy](#version-support-policy) above.
|
|
225
|
+
|
|
226
|
+
**Q: What if migration tool doesn't work?**
|
|
227
|
+
A: File an issue with details. Manual migration is always an option using the guides.
|
|
228
|
+
|
|
229
|
+
**Q: Should I upgrade immediately?**
|
|
230
|
+
A: For patches, yes. For minor/major versions, test in staging first.
|
|
231
|
+
|
|
232
|
+
**Q: Can I stay on old version?**
|
|
233
|
+
A: Yes, but you won't get security fixes after support ends. Plan upgrades accordingly.
|
|
@@ -0,0 +1,475 @@
|
|
|
1
|
+
# Recipe: Adding Animations
|
|
2
|
+
|
|
3
|
+
Guide to adding smooth, professional animations using Framer Motion.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
The framework uses Framer Motion for animations. This recipe covers:
|
|
8
|
+
- Basic fade and slide animations
|
|
9
|
+
- Stagger effects for lists
|
|
10
|
+
- Scroll-triggered animations
|
|
11
|
+
- Respecting user motion preferences
|
|
12
|
+
- Performance optimization
|
|
13
|
+
|
|
14
|
+
## Prerequisites
|
|
15
|
+
|
|
16
|
+
Framer Motion is a peer dependency:
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
npm install framer-motion
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Basic Animations
|
|
23
|
+
|
|
24
|
+
### Fade In
|
|
25
|
+
|
|
26
|
+
```tsx
|
|
27
|
+
import { motion } from 'framer-motion'
|
|
28
|
+
|
|
29
|
+
function FadeInExample() {
|
|
30
|
+
return (
|
|
31
|
+
<motion.div
|
|
32
|
+
initial={{ opacity: 0 }}
|
|
33
|
+
animate={{ opacity: 1 }}
|
|
34
|
+
transition={{ duration: 0.5 }}
|
|
35
|
+
>
|
|
36
|
+
<h1>This fades in</h1>
|
|
37
|
+
</motion.div>
|
|
38
|
+
)
|
|
39
|
+
}
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### Slide In
|
|
43
|
+
|
|
44
|
+
```tsx
|
|
45
|
+
import { motion } from 'framer-motion'
|
|
46
|
+
|
|
47
|
+
function SlideInExample() {
|
|
48
|
+
return (
|
|
49
|
+
<motion.div
|
|
50
|
+
initial={{ x: -50, opacity: 0 }}
|
|
51
|
+
animate={{ x: 0, opacity: 1 }}
|
|
52
|
+
transition={{ duration: 0.5 }}
|
|
53
|
+
>
|
|
54
|
+
<h1>This slides in from left</h1>
|
|
55
|
+
</motion.div>
|
|
56
|
+
)
|
|
57
|
+
}
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### Fade In Up (Most Common)
|
|
61
|
+
|
|
62
|
+
```tsx
|
|
63
|
+
import { motion } from 'framer-motion'
|
|
64
|
+
|
|
65
|
+
function FadeInUpExample() {
|
|
66
|
+
return (
|
|
67
|
+
<motion.div
|
|
68
|
+
initial={{ y: 20, opacity: 0 }}
|
|
69
|
+
animate={{ y: 0, opacity: 1 }}
|
|
70
|
+
transition={{ duration: 0.6, ease: 'easeOut' }}
|
|
71
|
+
>
|
|
72
|
+
<h1>This fades in while moving up</h1>
|
|
73
|
+
</motion.div>
|
|
74
|
+
)
|
|
75
|
+
}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## Stagger Animations
|
|
79
|
+
|
|
80
|
+
Animate lists with staggered timing:
|
|
81
|
+
|
|
82
|
+
```tsx
|
|
83
|
+
import { motion } from 'framer-motion'
|
|
84
|
+
|
|
85
|
+
const container = {
|
|
86
|
+
hidden: { opacity: 0 },
|
|
87
|
+
show: {
|
|
88
|
+
opacity: 1,
|
|
89
|
+
transition: {
|
|
90
|
+
staggerChildren: 0.1
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const item = {
|
|
96
|
+
hidden: { y: 20, opacity: 0 },
|
|
97
|
+
show: { y: 0, opacity: 1 }
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function StaggeredList({ items }) {
|
|
101
|
+
return (
|
|
102
|
+
<motion.ul
|
|
103
|
+
variants={container}
|
|
104
|
+
initial="hidden"
|
|
105
|
+
animate="show"
|
|
106
|
+
>
|
|
107
|
+
{items.map((item) => (
|
|
108
|
+
<motion.li key={item.id} variants={item}>
|
|
109
|
+
{item.name}
|
|
110
|
+
</motion.li>
|
|
111
|
+
))}
|
|
112
|
+
</motion.ul>
|
|
113
|
+
)
|
|
114
|
+
}
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## Scroll-Triggered Animations
|
|
118
|
+
|
|
119
|
+
Animate when element enters viewport:
|
|
120
|
+
|
|
121
|
+
```tsx
|
|
122
|
+
import { motion, useInView } from 'framer-motion'
|
|
123
|
+
import { useRef } from 'react'
|
|
124
|
+
|
|
125
|
+
function ScrollReveal({ children }) {
|
|
126
|
+
const ref = useRef(null)
|
|
127
|
+
const isInView = useInView(ref, { once: true, amount: 0.3 })
|
|
128
|
+
|
|
129
|
+
return (
|
|
130
|
+
<motion.div
|
|
131
|
+
ref={ref}
|
|
132
|
+
initial={{ y: 50, opacity: 0 }}
|
|
133
|
+
animate={isInView ? { y: 0, opacity: 1 } : { y: 50, opacity: 0 }}
|
|
134
|
+
transition={{ duration: 0.6, ease: 'easeOut' }}
|
|
135
|
+
>
|
|
136
|
+
{children}
|
|
137
|
+
</motion.div>
|
|
138
|
+
)
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// Usage
|
|
142
|
+
<ScrollReveal>
|
|
143
|
+
<h2>This animates when scrolled into view</h2>
|
|
144
|
+
</ScrollReveal>
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
## Respecting User Preferences
|
|
148
|
+
|
|
149
|
+
Always respect `prefers-reduced-motion`:
|
|
150
|
+
|
|
151
|
+
```tsx
|
|
152
|
+
import { motion, useReducedMotion } from 'framer-motion'
|
|
153
|
+
|
|
154
|
+
function AccessibleAnimation({ children }) {
|
|
155
|
+
const shouldReduceMotion = useReducedMotion()
|
|
156
|
+
|
|
157
|
+
return (
|
|
158
|
+
<motion.div
|
|
159
|
+
initial={{ opacity: 0, y: shouldReduceMotion ? 0 : 20 }}
|
|
160
|
+
animate={{ opacity: 1, y: 0 }}
|
|
161
|
+
transition={{
|
|
162
|
+
duration: shouldReduceMotion ? 0 : 0.6,
|
|
163
|
+
ease: 'easeOut'
|
|
164
|
+
}}
|
|
165
|
+
>
|
|
166
|
+
{children}
|
|
167
|
+
</motion.div>
|
|
168
|
+
)
|
|
169
|
+
}
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
## Reusable Animation Component
|
|
173
|
+
|
|
174
|
+
Create a flexible animation wrapper:
|
|
175
|
+
|
|
176
|
+
```tsx
|
|
177
|
+
import { motion, useReducedMotion, useInView } from 'framer-motion'
|
|
178
|
+
import { useRef } from 'react'
|
|
179
|
+
|
|
180
|
+
type AnimationType = 'fadeIn' | 'fadeInUp' | 'slideInLeft' | 'slideInRight'
|
|
181
|
+
|
|
182
|
+
interface AnimatedSectionProps {
|
|
183
|
+
children: React.ReactNode
|
|
184
|
+
type?: AnimationType
|
|
185
|
+
delay?: number
|
|
186
|
+
duration?: number
|
|
187
|
+
once?: boolean
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
const animations: Record<AnimationType, any> = {
|
|
191
|
+
fadeIn: {
|
|
192
|
+
hidden: { opacity: 0 },
|
|
193
|
+
visible: { opacity: 1 }
|
|
194
|
+
},
|
|
195
|
+
fadeInUp: {
|
|
196
|
+
hidden: { y: 20, opacity: 0 },
|
|
197
|
+
visible: { y: 0, opacity: 1 }
|
|
198
|
+
},
|
|
199
|
+
slideInLeft: {
|
|
200
|
+
hidden: { x: -50, opacity: 0 },
|
|
201
|
+
visible: { x: 0, opacity: 1 }
|
|
202
|
+
},
|
|
203
|
+
slideInRight: {
|
|
204
|
+
hidden: { x: 50, opacity: 0 },
|
|
205
|
+
visible: { x: 0, opacity: 1 }
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
export function AnimatedSection({
|
|
210
|
+
children,
|
|
211
|
+
type = 'fadeInUp',
|
|
212
|
+
delay = 0,
|
|
213
|
+
duration = 0.6,
|
|
214
|
+
once = true
|
|
215
|
+
}: AnimatedSectionProps) {
|
|
216
|
+
const ref = useRef(null)
|
|
217
|
+
const isInView = useInView(ref, { once, amount: 0.3 })
|
|
218
|
+
const shouldReduceMotion = useReducedMotion()
|
|
219
|
+
|
|
220
|
+
const animation = animations[type]
|
|
221
|
+
|
|
222
|
+
return (
|
|
223
|
+
<motion.div
|
|
224
|
+
ref={ref}
|
|
225
|
+
initial="hidden"
|
|
226
|
+
animate={isInView ? 'visible' : 'hidden'}
|
|
227
|
+
variants={shouldReduceMotion ? {} : animation}
|
|
228
|
+
transition={{
|
|
229
|
+
duration: shouldReduceMotion ? 0 : duration,
|
|
230
|
+
delay: shouldReduceMotion ? 0 : delay,
|
|
231
|
+
ease: 'easeOut'
|
|
232
|
+
}}
|
|
233
|
+
>
|
|
234
|
+
{children}
|
|
235
|
+
</motion.div>
|
|
236
|
+
)
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
// Usage
|
|
240
|
+
<AnimatedSection type="fadeInUp" delay={0.2}>
|
|
241
|
+
<h1>Animated Heading</h1>
|
|
242
|
+
</AnimatedSection>
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
## Button Hover Effects
|
|
246
|
+
|
|
247
|
+
```tsx
|
|
248
|
+
import { motion } from 'framer-motion'
|
|
249
|
+
|
|
250
|
+
function AnimatedButton({ children, onClick }) {
|
|
251
|
+
return (
|
|
252
|
+
<motion.button
|
|
253
|
+
onClick={onClick}
|
|
254
|
+
whileHover={{ scale: 1.05 }}
|
|
255
|
+
whileTap={{ scale: 0.95 }}
|
|
256
|
+
transition={{ type: 'spring', stiffness: 400, damping: 17 }}
|
|
257
|
+
className="px-6 py-3 bg-primary text-white rounded"
|
|
258
|
+
>
|
|
259
|
+
{children}
|
|
260
|
+
</motion.button>
|
|
261
|
+
)
|
|
262
|
+
}
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
## Card Hover Effects
|
|
266
|
+
|
|
267
|
+
```tsx
|
|
268
|
+
import { motion } from 'framer-motion'
|
|
269
|
+
|
|
270
|
+
function Card({ title, description }) {
|
|
271
|
+
return (
|
|
272
|
+
<motion.div
|
|
273
|
+
whileHover={{
|
|
274
|
+
y: -8,
|
|
275
|
+
boxShadow: '0 20px 40px rgba(0, 0, 0, 0.15)'
|
|
276
|
+
}}
|
|
277
|
+
transition={{ duration: 0.3, ease: 'easeOut' }}
|
|
278
|
+
className="p-6 bg-white rounded-lg shadow"
|
|
279
|
+
>
|
|
280
|
+
<h3>{title}</h3>
|
|
281
|
+
<p>{description}</p>
|
|
282
|
+
</motion.div>
|
|
283
|
+
)
|
|
284
|
+
}
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
## Page Transitions
|
|
288
|
+
|
|
289
|
+
```tsx
|
|
290
|
+
import { motion, AnimatePresence } from 'framer-motion'
|
|
291
|
+
import { usePathname } from 'next/navigation'
|
|
292
|
+
|
|
293
|
+
export function PageTransition({ children }) {
|
|
294
|
+
const pathname = usePathname()
|
|
295
|
+
|
|
296
|
+
return (
|
|
297
|
+
<AnimatePresence mode="wait">
|
|
298
|
+
<motion.div
|
|
299
|
+
key={pathname}
|
|
300
|
+
initial={{ opacity: 0, y: 20 }}
|
|
301
|
+
animate={{ opacity: 1, y: 0 }}
|
|
302
|
+
exit={{ opacity: 0, y: -20 }}
|
|
303
|
+
transition={{ duration: 0.3 }}
|
|
304
|
+
>
|
|
305
|
+
{children}
|
|
306
|
+
</motion.div>
|
|
307
|
+
</AnimatePresence>
|
|
308
|
+
)
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
// In layout
|
|
312
|
+
<PageTransition>
|
|
313
|
+
{children}
|
|
314
|
+
</PageTransition>
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
## Performance Tips
|
|
318
|
+
|
|
319
|
+
### 1. Animate Transform and Opacity
|
|
320
|
+
|
|
321
|
+
Prefer `transform` and `opacity` for best performance:
|
|
322
|
+
|
|
323
|
+
```tsx
|
|
324
|
+
// Good - uses GPU acceleration
|
|
325
|
+
<motion.div
|
|
326
|
+
animate={{ x: 100, opacity: 0.5 }}
|
|
327
|
+
/>
|
|
328
|
+
|
|
329
|
+
// Avoid - forces layout recalculation
|
|
330
|
+
<motion.div
|
|
331
|
+
animate={{ width: 100, marginLeft: 20 }}
|
|
332
|
+
/>
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
### 2. Use willChange Sparingly
|
|
336
|
+
|
|
337
|
+
```tsx
|
|
338
|
+
<motion.div
|
|
339
|
+
style={{ willChange: 'transform' }}
|
|
340
|
+
animate={{ x: 100 }}
|
|
341
|
+
/>
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
### 3. Lazy Load Framer Motion
|
|
345
|
+
|
|
346
|
+
```tsx
|
|
347
|
+
import dynamic from 'next/dynamic'
|
|
348
|
+
|
|
349
|
+
const AnimatedSection = dynamic(
|
|
350
|
+
() => import('./AnimatedSection'),
|
|
351
|
+
{ ssr: false }
|
|
352
|
+
)
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
### 4. Disable Animations on Low-End Devices
|
|
356
|
+
|
|
357
|
+
```tsx
|
|
358
|
+
const shouldAnimate = !shouldReduceMotion && !isLowEndDevice()
|
|
359
|
+
|
|
360
|
+
<motion.div
|
|
361
|
+
animate={shouldAnimate ? { opacity: 1 } : {}}
|
|
362
|
+
>
|
|
363
|
+
{children}
|
|
364
|
+
</motion.div>
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
## Common Patterns
|
|
368
|
+
|
|
369
|
+
### Hero Section Entrance
|
|
370
|
+
|
|
371
|
+
```tsx
|
|
372
|
+
<motion.div
|
|
373
|
+
initial={{ opacity: 0, y: 30 }}
|
|
374
|
+
animate={{ opacity: 1, y: 0 }}
|
|
375
|
+
transition={{ duration: 0.8, ease: 'easeOut' }}
|
|
376
|
+
>
|
|
377
|
+
<h1>Welcome</h1>
|
|
378
|
+
</motion.div>
|
|
379
|
+
|
|
380
|
+
<motion.p
|
|
381
|
+
initial={{ opacity: 0 }}
|
|
382
|
+
animate={{ opacity: 1 }}
|
|
383
|
+
transition={{ delay: 0.3, duration: 0.6 }}
|
|
384
|
+
>
|
|
385
|
+
Subheadline
|
|
386
|
+
</motion.p>
|
|
387
|
+
|
|
388
|
+
<motion.div
|
|
389
|
+
initial={{ opacity: 0, y: 20 }}
|
|
390
|
+
animate={{ opacity: 1, y: 0 }}
|
|
391
|
+
transition={{ delay: 0.6, duration: 0.6 }}
|
|
392
|
+
>
|
|
393
|
+
<Button>Get Started</Button>
|
|
394
|
+
</motion.div>
|
|
395
|
+
```
|
|
396
|
+
|
|
397
|
+
### Feature Grid
|
|
398
|
+
|
|
399
|
+
```tsx
|
|
400
|
+
const container = {
|
|
401
|
+
hidden: {},
|
|
402
|
+
show: {
|
|
403
|
+
transition: {
|
|
404
|
+
staggerChildren: 0.1
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
const item = {
|
|
410
|
+
hidden: { y: 20, opacity: 0 },
|
|
411
|
+
show: {
|
|
412
|
+
y: 0,
|
|
413
|
+
opacity: 1,
|
|
414
|
+
transition: { duration: 0.5 }
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
<motion.div
|
|
419
|
+
variants={container}
|
|
420
|
+
initial="hidden"
|
|
421
|
+
whileInView="show"
|
|
422
|
+
viewport={{ once: true }}
|
|
423
|
+
className="grid grid-cols-3 gap-6"
|
|
424
|
+
>
|
|
425
|
+
{features.map((feature) => (
|
|
426
|
+
<motion.div key={feature.id} variants={item}>
|
|
427
|
+
<FeatureCard {...feature} />
|
|
428
|
+
</motion.div>
|
|
429
|
+
))}
|
|
430
|
+
</motion.div>
|
|
431
|
+
```
|
|
432
|
+
|
|
433
|
+
## Best Practices
|
|
434
|
+
|
|
435
|
+
1. **Keep it Subtle**
|
|
436
|
+
- Duration: 0.3-0.8s
|
|
437
|
+
- Easing: 'easeOut' or 'easeInOut'
|
|
438
|
+
- Movement: 20-50px max
|
|
439
|
+
|
|
440
|
+
2. **Respect Preferences**
|
|
441
|
+
- Always use `useReducedMotion()`
|
|
442
|
+
- Provide alternative feedback
|
|
443
|
+
|
|
444
|
+
3. **Performance**
|
|
445
|
+
- Animate transform and opacity only
|
|
446
|
+
- Use `whileInView` for scroll animations
|
|
447
|
+
- Lazy load when possible
|
|
448
|
+
|
|
449
|
+
4. **Purpose**
|
|
450
|
+
- Guide attention
|
|
451
|
+
- Provide feedback
|
|
452
|
+
- Establish hierarchy
|
|
453
|
+
- Don't animate for decoration only
|
|
454
|
+
|
|
455
|
+
5. **Accessibility**
|
|
456
|
+
- Don't rely on animation to convey information
|
|
457
|
+
- Provide text alternatives
|
|
458
|
+
- Keep animations brief
|
|
459
|
+
- Test with animations disabled
|
|
460
|
+
|
|
461
|
+
## Timing Guidelines
|
|
462
|
+
|
|
463
|
+
- **Micro-interactions**: 100-300ms
|
|
464
|
+
- **Component entrance**: 300-600ms
|
|
465
|
+
- **Page transitions**: 300-500ms
|
|
466
|
+
- **Stagger delay**: 50-150ms between items
|
|
467
|
+
- **Hover effects**: 200-300ms
|
|
468
|
+
|
|
469
|
+
## Easing Functions
|
|
470
|
+
|
|
471
|
+
- **easeOut**: Starting fast, ending slow (most common)
|
|
472
|
+
- **easeIn**: Starting slow, ending fast (exits)
|
|
473
|
+
- **easeInOut**: Slow start and end (smooth)
|
|
474
|
+
- **spring**: Bouncy, playful feel
|
|
475
|
+
- **linear**: Robotic, avoid for most cases
|