@polymorphism-tech/morph-spec 7.0.0 → 7.1.1
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/README.md +368 -368
- package/claude-plugin.json +14 -14
- package/docs/CHEATSHEET.md +199 -199
- package/docs/QUICKSTART.md +200 -200
- package/framework/CLAUDE.md +1 -1
- package/framework/MORPH.md +4 -1
- package/framework/agents.json +132 -127
- package/framework/rubrics/backend.json +41 -36
- package/framework/rules/ai-agents-standards.md +45 -15
- package/framework/rules/neon-standards.md +25 -26
- package/framework/skills/core/morph-brainstorming/SKILL.md +1 -1
- package/framework/skills/core/morph-plan/SKILL.md +3 -1
- package/framework/skills/core/morph-stack-scan/SKILL.md +3 -3
- package/framework/standards/STANDARDS.json +1729 -1133
- package/framework/standards/ai-agents/agent-session.md +160 -0
- package/framework/standards/ai-agents/batching.md +193 -0
- package/framework/standards/ai-agents/context-providers.md +188 -0
- package/framework/standards/ai-agents/mcp-server.md +250 -0
- package/framework/standards/ai-agents/mcp-tools.md +197 -0
- package/framework/standards/ai-agents/middleware-patterns.md +207 -0
- package/framework/standards/ai-agents/modalities-image-gen.md +173 -0
- package/framework/standards/ai-agents/modalities-speech-to-text.md +171 -0
- package/framework/standards/ai-agents/modalities-text-to-speech.md +181 -0
- package/framework/standards/ai-agents/modalities-vision.md +201 -0
- package/framework/standards/ai-agents/multi-agent-patterns.md +155 -0
- package/framework/standards/ai-agents/production.md +114 -258
- package/framework/standards/ai-agents/prompts-in-db.md +214 -0
- package/framework/standards/ai-agents/providers/model-registry.md +158 -0
- package/framework/standards/ai-agents/rag-custom-pgvector.md +243 -0
- package/framework/standards/ai-agents/service-tier-flex.md +135 -0
- package/framework/standards/ai-agents/setup.md +142 -316
- package/framework/standards/ai-agents/structured-output.md +249 -0
- package/framework/standards/ai-agents/sweet-spot.md +109 -0
- package/framework/standards/ai-agents/workflows.md +114 -284
- package/framework/standards/architecture/vertical-slice/vertical-slice.md +439 -429
- package/framework/standards/backend/api/validation.md +92 -88
- package/framework/standards/backend/database/postgresql/database.md +336 -332
- package/framework/standards/backend/database/vector-search-rag.md +599 -541
- package/framework/standards/backend/dotnet/fluent-validation-vsa.md +4 -0
- package/framework/standards/backend/dotnet/result-pattern.md +4 -0
- package/framework/standards/backend/dotnet/scalar-ui.md +176 -172
- package/framework/standards/backend/dotnet/scrutor.md +4 -0
- package/framework/standards/backend/dotnet/vsa-handler-patterns.md +310 -274
- package/framework/standards/backend/integrations/asaas/asaas-api.md +260 -216
- package/framework/standards/backend/integrations/hangfire/hangfire-jobs.md +354 -350
- package/framework/standards/backend/integrations/neon-auth/neon-auth.md +30 -19
- package/framework/standards/backend/integrations/resend/resend-email.md +400 -385
- package/framework/standards/data/nosql/cache/redis.md +106 -97
- package/framework/standards/data/nosql/cosmos-db.md +127 -118
- package/framework/standards/data/vector-search/rag-chunking.md +113 -104
- package/framework/standards/frontend/design-system/ai-image-generation.md +4 -0
- package/framework/standards/frontend/design-system/animations.md +164 -160
- package/framework/standards/frontend/design-system/naming.md +68 -64
- package/framework/standards/frontend/gsap/gsap-core.md +14 -8
- package/framework/standards/frontend/gsap/gsap-plugins.md +26 -21
- package/framework/standards/frontend/gsap/gsap-scrolltrigger.md +9 -7
- package/framework/standards/frontend/nextjs/app-router.md +127 -123
- package/framework/standards/frontend/nextjs/components.md +136 -132
- package/framework/standards/frontend/nextjs/data-fetching.md +130 -126
- package/framework/standards/frontend/nextjs/forms.md +134 -128
- package/framework/standards/frontend/nextjs/motion-patterns.md +328 -322
- package/framework/standards/frontend/nextjs/naming-conventions.md +71 -67
- package/framework/standards/frontend/nextjs/nextjs-patterns.md +229 -225
- package/framework/standards/frontend/nextjs/project-structure.md +106 -102
- package/framework/standards/frontend/nextjs/state-management.md +76 -72
- package/framework/standards/frontend/nextjs/testing.md +115 -111
- package/framework/standards/infrastructure/docker/easypanel-deploy.md +196 -192
- package/framework/standards/infrastructure/neon/neon-pgrag.md +6 -2
- package/framework/standards/infrastructure/neon/neon-pgvector.md +4 -0
- package/framework/standards/infrastructure/neon/neon-setup.md +5 -1
- package/framework/standards/integration/mcp/mcp-tools.md +471 -462
- package/framework/templates/CLAUDE.md.core.template +1 -1
- package/framework/templates/REGISTRY.json +1745 -1239
- package/framework/templates/code/dotnet/ai-agents/AgentBootstrap.cs.template +39 -0
- package/framework/templates/code/dotnet/ai-agents/EmbeddingService.cs.template +68 -0
- package/framework/templates/code/dotnet/ai-agents/ModelRegistry.cs.template +117 -0
- package/framework/templates/code/dotnet/ai-agents/PromptRepository.cs.template +95 -0
- package/framework/templates/code/dotnet/ai-agents/ResilientToolMiddleware.cs.template +61 -0
- package/framework/templates/code/dotnet/ai-agents/VectorSearchTool.cs.template +107 -0
- package/framework/templates/code/dotnet/ai-agents/model-registry.json.template +58 -0
- package/framework/templates/code/dotnet/backend/repository.cs +3 -10
- package/framework/templates/code/sql/ai-agents/agent-prompts-migration.sql.template +58 -0
- package/framework/templates/code/sql/ai-agents/pgvector-embeddings-migration.sql.template +91 -0
- package/package.json +89 -83
- package/src/core/templates/template-registry.js +289 -256
- package/src/lib/generators/context-generator.js +516 -518
- package/src/lib/generators/scaffold-generator.js +23 -26
- package/framework/standards/infrastructure/neon/neon-semantic-kernel.md +0 -310
- package/framework/templates/integrations/semantic-kernel-neon.cs +0 -125
|
@@ -1,104 +1,113 @@
|
|
|
1
|
-
# Data Standard: RAG Chunking Strategies
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
{
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
//
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
##
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
1
|
+
# Data Standard: RAG Chunking Strategies
|
|
2
|
+
|
|
3
|
+
> **Scope:** data-vector-search
|
|
4
|
+
> **Layer:** 2
|
|
5
|
+
> **Keywords:** chunking, rag, embeddings, vector-search, document-segmentation, overlap, retrieval
|
|
6
|
+
> **Load When:** building a RAG pipeline or embedding documents for vector search
|
|
7
|
+
|
|
8
|
+
**Verified against:** .NET 10 (chunking algorithms — language-level, no external package). Last-verified: 2026-05-20.
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## Overview
|
|
13
|
+
Chunking splits documents into segments for embedding. Chunk quality directly impacts RAG answer quality.
|
|
14
|
+
|
|
15
|
+
## Chunking Strategies
|
|
16
|
+
|
|
17
|
+
### 1. Fixed-Size (Baseline)
|
|
18
|
+
```csharp
|
|
19
|
+
public IEnumerable<Chunk> FixedSizeChunk(string text, int size = 512, int overlap = 50)
|
|
20
|
+
{
|
|
21
|
+
for (int i = 0; i < text.Length; i += size - overlap)
|
|
22
|
+
{
|
|
23
|
+
yield return new Chunk
|
|
24
|
+
{
|
|
25
|
+
Content = text[i..Math.Min(i + size, text.Length)],
|
|
26
|
+
StartIndex = i,
|
|
27
|
+
EndIndex = Math.Min(i + size, text.Length)
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### 2. Sentence-Aware (Recommended for prose)
|
|
34
|
+
```csharp
|
|
35
|
+
public IEnumerable<Chunk> SentenceChunk(string text, int maxTokens = 256)
|
|
36
|
+
{
|
|
37
|
+
var sentences = SplitSentences(text);
|
|
38
|
+
var current = new StringBuilder();
|
|
39
|
+
var tokenCount = 0;
|
|
40
|
+
|
|
41
|
+
foreach (var sentence in sentences)
|
|
42
|
+
{
|
|
43
|
+
var sentenceTokens = EstimateTokens(sentence);
|
|
44
|
+
if (tokenCount + sentenceTokens > maxTokens && current.Length > 0)
|
|
45
|
+
{
|
|
46
|
+
yield return new Chunk { Content = current.ToString().Trim() };
|
|
47
|
+
current.Clear();
|
|
48
|
+
tokenCount = 0;
|
|
49
|
+
}
|
|
50
|
+
current.Append(sentence).Append(' ');
|
|
51
|
+
tokenCount += sentenceTokens;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if (current.Length > 0)
|
|
55
|
+
yield return new Chunk { Content = current.ToString().Trim() };
|
|
56
|
+
}
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### 3. Semantic (Best quality, higher cost)
|
|
60
|
+
Split at semantic boundaries (paragraphs, headers, sections) rather than character count.
|
|
61
|
+
|
|
62
|
+
```csharp
|
|
63
|
+
public IEnumerable<Chunk> SemanticChunk(string markdown)
|
|
64
|
+
{
|
|
65
|
+
// Split at markdown headers
|
|
66
|
+
var sections = Regex.Split(markdown, @"(?=^#{1,3} )", RegexOptions.Multiline);
|
|
67
|
+
foreach (var section in sections.Where(s => s.Trim().Length > 0))
|
|
68
|
+
yield return new Chunk { Content = section.Trim() };
|
|
69
|
+
}
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## Token Estimation
|
|
73
|
+
```csharp
|
|
74
|
+
// Rough estimate: 1 token ≈ 4 characters (English), ≈ 3 characters (Portuguese)
|
|
75
|
+
private static int EstimateTokens(string text) => text.Length / 4;
|
|
76
|
+
|
|
77
|
+
// More accurate: use tiktoken (if available)
|
|
78
|
+
// var encoder = TiktokenSharp.TikToken.EncodingForModel("gpt-4");
|
|
79
|
+
// return encoder.Encode(text).Count;
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## Chunk Metadata
|
|
83
|
+
Always store metadata with chunks for filtering and citation:
|
|
84
|
+
```csharp
|
|
85
|
+
public record Chunk
|
|
86
|
+
{
|
|
87
|
+
public string Content { get; init; } = "";
|
|
88
|
+
public string DocumentId { get; init; } = "";
|
|
89
|
+
public string DocumentTitle { get; init; } = "";
|
|
90
|
+
public string SourceUrl { get; init; } = "";
|
|
91
|
+
public int ChunkIndex { get; init; }
|
|
92
|
+
public int StartCharIndex { get; init; }
|
|
93
|
+
public string Section { get; init; } = ""; // H1/H2 header this belongs to
|
|
94
|
+
public DateTime IndexedAt { get; init; } = DateTime.UtcNow;
|
|
95
|
+
}
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
## Strategy Selection Guide
|
|
99
|
+
| Document Type | Strategy | Chunk Size |
|
|
100
|
+
|---------------|----------|------------|
|
|
101
|
+
| Legal documents | Sentence-aware | 256 tokens |
|
|
102
|
+
| Technical docs | Semantic (headers) | Variable |
|
|
103
|
+
| Q&A pairs | Keep as-is | Whole Q+A |
|
|
104
|
+
| Code files | Function-boundary | Whole function |
|
|
105
|
+
| News articles | Paragraph | 512 tokens |
|
|
106
|
+
|
|
107
|
+
## Quality Checklist
|
|
108
|
+
- [ ] Chunks overlap by 10-20% to avoid cutting context at boundaries
|
|
109
|
+
- [ ] Minimum chunk size: 50 tokens (avoid noisy small chunks)
|
|
110
|
+
- [ ] Maximum chunk size: ~512 tokens (well under the 8192-token input limit of `text-embedding-3-small`/`-large`)
|
|
111
|
+
- [ ] Metadata preserved and searchable
|
|
112
|
+
- [ ] Source URL included for citation
|
|
113
|
+
- [ ] Re-index when document changes (detect via content hash)
|
|
@@ -5,6 +5,10 @@
|
|
|
5
5
|
> **Keywords:** image, gemini, asset, ai-generation, placeholder, mcp, next/image
|
|
6
6
|
> **Load When:** feature has UI components requiring image assets
|
|
7
7
|
|
|
8
|
+
**Verified against:** Gemini Image MCP + Next.js 15 `next/image`. Last-verified: 2026-05-20.
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
8
12
|
## When to Use AI-Generated Images
|
|
9
13
|
|
|
10
14
|
| Use Case | Approach | Examples |
|
|
@@ -1,160 +1,164 @@
|
|
|
1
|
-
# CSS Animation Patterns
|
|
2
|
-
|
|
3
|
-
> **Scope:** universal
|
|
4
|
-
> **Layer:** 0 (always load)
|
|
5
|
-
> **Keywords:** css, animation, keyframe, transition, stagger, shimmer
|
|
6
|
-
> **Load When:** always
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
@keyframes
|
|
16
|
-
@keyframes
|
|
17
|
-
@keyframes
|
|
18
|
-
@keyframes
|
|
19
|
-
@keyframes
|
|
20
|
-
@keyframes
|
|
21
|
-
@keyframes
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
|
31
|
-
|
|
32
|
-
| `.animate-
|
|
33
|
-
| `.animate-
|
|
34
|
-
| `.animate-
|
|
35
|
-
| `.animate-
|
|
36
|
-
| `.animate-
|
|
37
|
-
| `.animate-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
```
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
```
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
/*
|
|
53
|
-
.
|
|
54
|
-
.
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
.
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
@
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
```
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
```
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
.
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
.
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
```
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
- [ ]
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
1
|
+
# CSS Animation Patterns
|
|
2
|
+
|
|
3
|
+
> **Scope:** universal
|
|
4
|
+
> **Layer:** 0 (always load)
|
|
5
|
+
> **Keywords:** css, animation, keyframe, transition, stagger, shimmer
|
|
6
|
+
> **Load When:** always
|
|
7
|
+
|
|
8
|
+
**Verified against:** CSS animations/transitions (language-level, no framework). Last-verified: 2026-05-20.
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## Keyframes Library
|
|
13
|
+
|
|
14
|
+
```css
|
|
15
|
+
@keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }
|
|
16
|
+
@keyframes fadeOut { from { opacity: 1; } to { opacity: 0; } }
|
|
17
|
+
@keyframes slideInUp { from { opacity: 0; transform: translateY(20px); } to { opacity: 1; transform: translateY(0); } }
|
|
18
|
+
@keyframes slideInDown { from { opacity: 0; transform: translateY(-20px); } to { opacity: 1; transform: translateY(0); } }
|
|
19
|
+
@keyframes slideInLeft { from { opacity: 0; transform: translateX(-20px); } to { opacity: 1; transform: translateX(0); } }
|
|
20
|
+
@keyframes slideInRight { from { opacity: 0; transform: translateX(20px); } to { opacity: 1; transform: translateX(0); } }
|
|
21
|
+
@keyframes scaleIn { from { opacity: 0; transform: scale(0.95); } to { opacity: 1; transform: scale(1); } }
|
|
22
|
+
@keyframes bounce { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-10px); } }
|
|
23
|
+
@keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.5; } }
|
|
24
|
+
@keyframes spin { from { transform: rotate(0deg); } to { transform: rotate(360deg); } }
|
|
25
|
+
@keyframes shimmer { 0% { background-position: -200% 0; } 100% { background-position: 200% 0; } }
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Animation Classes
|
|
29
|
+
|
|
30
|
+
| Class | Animation | Duration | Iteration |
|
|
31
|
+
|-------|-----------|----------|-----------|
|
|
32
|
+
| `.animate-fadeIn` | fadeIn | 0.3s | once |
|
|
33
|
+
| `.animate-fadeOut` | fadeOut | 0.3s | once |
|
|
34
|
+
| `.animate-slideInUp` | slideInUp | 0.5s | once |
|
|
35
|
+
| `.animate-slideInDown` | slideInDown | 0.5s | once |
|
|
36
|
+
| `.animate-slideInLeft` | slideInLeft | 0.5s | once |
|
|
37
|
+
| `.animate-slideInRight` | slideInRight | 0.5s | once |
|
|
38
|
+
| `.animate-scaleIn` | scaleIn | 0.3s | once |
|
|
39
|
+
| `.animate-bounce` | bounce | 1s | infinite |
|
|
40
|
+
| `.animate-pulse` | pulse | 2s | infinite |
|
|
41
|
+
| `.animate-spin` | spin | 1s | infinite |
|
|
42
|
+
|
|
43
|
+
```css
|
|
44
|
+
.animate-fadeIn { animation: fadeIn 0.3s ease forwards; }
|
|
45
|
+
.animate-slideInUp { animation: slideInUp 0.5s ease forwards; }
|
|
46
|
+
.animate-bounce { animation: bounce 1s ease infinite; }
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Stagger & Timing
|
|
50
|
+
|
|
51
|
+
```css
|
|
52
|
+
/* Stagger delays (0.1s - 1.0s) */
|
|
53
|
+
.stagger-1 { animation-delay: 0.1s; } .stagger-2 { animation-delay: 0.2s; }
|
|
54
|
+
.stagger-3 { animation-delay: 0.3s; } /* ... up to .stagger-10 */
|
|
55
|
+
|
|
56
|
+
/* Durations */
|
|
57
|
+
.duration-fast { animation-duration: 150ms; }
|
|
58
|
+
.duration-normal { animation-duration: 300ms; }
|
|
59
|
+
.duration-slow { animation-duration: 500ms; }
|
|
60
|
+
|
|
61
|
+
/* Easing */
|
|
62
|
+
.ease-bounce { animation-timing-function: cubic-bezier(0.68, -0.55, 0.265, 1.55); }
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## Shimmer (Skeleton Loading)
|
|
66
|
+
|
|
67
|
+
```css
|
|
68
|
+
.shimmer {
|
|
69
|
+
background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
|
|
70
|
+
background-size: 200% 100%;
|
|
71
|
+
animation: shimmer 1.5s infinite;
|
|
72
|
+
}
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
## Blazor Usage
|
|
78
|
+
|
|
79
|
+
### Stagger Pattern
|
|
80
|
+
|
|
81
|
+
```razor
|
|
82
|
+
@for (int i = 0; i < _items.Count; i++)
|
|
83
|
+
{
|
|
84
|
+
var index = i;
|
|
85
|
+
<div class="card animate-slideInUp"
|
|
86
|
+
style="@($"animation-delay: {0.05 * index}s; animation-fill-mode: backwards;")">
|
|
87
|
+
@_items[index].Name
|
|
88
|
+
</div>
|
|
89
|
+
}
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
**CRITICAL:** Use `animation-fill-mode: backwards` to avoid flash before delay.
|
|
93
|
+
|
|
94
|
+
### Conditional Enter/Exit
|
|
95
|
+
|
|
96
|
+
```razor
|
|
97
|
+
@if (_showMessage)
|
|
98
|
+
{
|
|
99
|
+
<div class="@(_isEntering ? "animate-slideInUp" : "animate-fadeOut")">Msg</div>
|
|
100
|
+
}
|
|
101
|
+
@code {
|
|
102
|
+
private async Task HideMessage() {
|
|
103
|
+
_isEntering = false;
|
|
104
|
+
await Task.Delay(300); // wait for exit animation
|
|
105
|
+
_showMessage = false;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### Skeleton Loading
|
|
111
|
+
|
|
112
|
+
```razor
|
|
113
|
+
@if (_isLoading)
|
|
114
|
+
{
|
|
115
|
+
<div class="shimmer" style="width: 200px; height: 24px; border-radius: 4px;"></div>
|
|
116
|
+
}
|
|
117
|
+
else { <h2>@_title</h2> }
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
## Transitions (Hover/Focus)
|
|
121
|
+
|
|
122
|
+
```css
|
|
123
|
+
.card { transition: transform 0.2s ease, box-shadow 0.2s ease; }
|
|
124
|
+
.card:hover { transform: translateY(-4px); box-shadow: var(--shadow-lg); }
|
|
125
|
+
|
|
126
|
+
.button { transition: background-color 0.15s ease, transform 0.15s ease; }
|
|
127
|
+
.button:active { transform: scale(0.98); }
|
|
128
|
+
|
|
129
|
+
.link::after { content: ''; position: absolute; width: 0; height: 2px; background: var(--primary); transition: width 0.3s ease; }
|
|
130
|
+
.link:hover::after { width: 100%; }
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
## Accessibility
|
|
134
|
+
|
|
135
|
+
```css
|
|
136
|
+
@media (prefers-reduced-motion: reduce) {
|
|
137
|
+
*, *::before, *::after {
|
|
138
|
+
animation-duration: 0.01ms !important;
|
|
139
|
+
animation-iteration-count: 1 !important;
|
|
140
|
+
transition-duration: 0.01ms !important;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
## Checklist
|
|
146
|
+
|
|
147
|
+
- [ ] Keyframes in design-system.css
|
|
148
|
+
- [ ] `.animate-*` classes created
|
|
149
|
+
- [ ] `animation-fill-mode: backwards` for stagger
|
|
150
|
+
- [ ] `@media (prefers-reduced-motion)` implemented
|
|
151
|
+
- [ ] Shimmer for loading states
|
|
152
|
+
|
|
153
|
+
## JavaScript Animation Libraries
|
|
154
|
+
|
|
155
|
+
For animations beyond CSS capabilities:
|
|
156
|
+
|
|
157
|
+
| Need | Library | Standard |
|
|
158
|
+
|------|---------|----------|
|
|
159
|
+
| Simple UI transitions (enter/exit, layout, gestures) | Motion (formerly Framer Motion) | `frontend/nextjs/motion-patterns.md` |
|
|
160
|
+
| Complex animations (ScrollTrigger, SVG morph, timelines) | GSAP | `frontend/gsap/gsap-core.md` |
|
|
161
|
+
|
|
162
|
+
---
|
|
163
|
+
|
|
164
|
+
*MORPH-SPEC by Polymorphism Tech*
|