@polymorphism-tech/morph-spec 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/README.md +279 -0
- package/bin/morph-spec.js +53 -0
- package/content/.claude/commands/morph-apply.md +66 -0
- package/content/.claude/commands/morph-archive.md +79 -0
- package/content/.claude/commands/morph-costs.md +206 -0
- package/content/.claude/commands/morph-infra.md +209 -0
- package/content/.claude/commands/morph-proposal.md +60 -0
- package/content/.claude/commands/morph-status.md +71 -0
- package/content/.claude/settings.local.json +15 -0
- package/content/.claude/skills/infra/bicep-architect.md +419 -0
- package/content/.claude/skills/infra/container-specialist.md +437 -0
- package/content/.claude/skills/infra/devops-engineer.md +405 -0
- package/content/.claude/skills/integrations/asaas-financial.md +333 -0
- package/content/.claude/skills/integrations/azure-identity.md +309 -0
- package/content/.claude/skills/integrations/clerk-auth.md +290 -0
- package/content/.claude/skills/specialists/azure-architect.md +142 -0
- package/content/.claude/skills/specialists/cost-guardian.md +110 -0
- package/content/.claude/skills/specialists/ef-modeler.md +200 -0
- package/content/.claude/skills/specialists/hangfire-orchestrator.md +245 -0
- package/content/.claude/skills/specialists/ms-agent-expert.md +209 -0
- package/content/.claude/skills/specialists/po-pm-advisor.md +197 -0
- package/content/.claude/skills/specialists/standards-architect.md +78 -0
- package/content/.claude/skills/specialists/ui-ux-designer.md +325 -0
- package/content/.claude/skills/stacks/dotnet-blazor.md +352 -0
- package/content/.claude/skills/stacks/dotnet-nextjs.md +402 -0
- package/content/.claude/skills/stacks/shopify.md +445 -0
- package/content/.morph/archive/.gitkeep +25 -0
- package/content/.morph/config/agents.json +149 -0
- package/content/.morph/config/config.template.json +96 -0
- package/content/.morph/examples/api-nextjs/README.md +241 -0
- package/content/.morph/examples/api-nextjs/contracts.ts +307 -0
- package/content/.morph/examples/api-nextjs/spec.md +399 -0
- package/content/.morph/examples/api-nextjs/tasks.md +168 -0
- package/content/.morph/examples/micro-saas/README.md +125 -0
- package/content/.morph/examples/micro-saas/contracts.cs +358 -0
- package/content/.morph/examples/micro-saas/decisions.md +246 -0
- package/content/.morph/examples/micro-saas/spec.md +236 -0
- package/content/.morph/examples/micro-saas/tasks.md +150 -0
- package/content/.morph/examples/multi-agent/README.md +309 -0
- package/content/.morph/examples/multi-agent/contracts.cs +433 -0
- package/content/.morph/examples/multi-agent/spec.md +479 -0
- package/content/.morph/examples/multi-agent/tasks.md +185 -0
- package/content/.morph/features/.gitkeep +25 -0
- package/content/.morph/project.md +159 -0
- package/content/.morph/specs/.gitkeep +20 -0
- package/content/.morph/standards/architecture.md +190 -0
- package/content/.morph/standards/azure.md +184 -0
- package/content/.morph/standards/coding.md +342 -0
- package/content/.morph/templates/agent.cs +172 -0
- package/content/.morph/templates/component.razor +239 -0
- package/content/.morph/templates/contracts.cs +217 -0
- package/content/.morph/templates/decisions.md +106 -0
- package/content/.morph/templates/infra/app-insights.bicep +63 -0
- package/content/.morph/templates/infra/container-app-env.bicep +49 -0
- package/content/.morph/templates/infra/container-app.bicep +156 -0
- package/content/.morph/templates/infra/key-vault.bicep +91 -0
- package/content/.morph/templates/infra/main.bicep +155 -0
- package/content/.morph/templates/infra/parameters.dev.json +23 -0
- package/content/.morph/templates/infra/parameters.prod.json +23 -0
- package/content/.morph/templates/infra/sql-database.bicep +103 -0
- package/content/.morph/templates/infra/storage.bicep +106 -0
- package/content/.morph/templates/integrations/asaas-client.cs +387 -0
- package/content/.morph/templates/integrations/asaas-webhook.cs +351 -0
- package/content/.morph/templates/integrations/azure-identity-config.cs +288 -0
- package/content/.morph/templates/integrations/clerk-config.cs +258 -0
- package/content/.morph/templates/job.cs +171 -0
- package/content/.morph/templates/migration.cs +83 -0
- package/content/.morph/templates/proposal.md +155 -0
- package/content/.morph/templates/recap.md +105 -0
- package/content/.morph/templates/repository.cs +141 -0
- package/content/.morph/templates/saas/subscription.cs +347 -0
- package/content/.morph/templates/saas/tenant.cs +338 -0
- package/content/.morph/templates/service.cs +139 -0
- package/content/.morph/templates/spec.md +147 -0
- package/content/.morph/templates/tasks.md +235 -0
- package/content/.morph/templates/test.cs +239 -0
- package/content/CLAUDE.md +318 -0
- package/package.json +50 -0
- package/src/commands/doctor.js +132 -0
- package/src/commands/init.js +121 -0
- package/src/commands/update.js +84 -0
- package/src/utils/file-copier.js +50 -0
- package/src/utils/logger.js +32 -0
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
# PO/PM Advisor
|
|
2
|
+
|
|
3
|
+
Especialista em requisitos, priorização e gestão de produto para clarificar features e ROI.
|
|
4
|
+
|
|
5
|
+
## Responsabilidades
|
|
6
|
+
|
|
7
|
+
1. **Clarificar requisitos** ambíguos ou incompletos
|
|
8
|
+
2. **Priorizar features** por valor de negócio
|
|
9
|
+
3. **Calcular ROI** e esforço estimado
|
|
10
|
+
4. **Definir critérios** de aceitação
|
|
11
|
+
|
|
12
|
+
## Triggers
|
|
13
|
+
|
|
14
|
+
Keywords: `unclear`, `requirements`, `priority`, `ROI`, `mvp`, `scope`, `acceptance criteria`, `user story`
|
|
15
|
+
|
|
16
|
+
## Framework de Clarificação
|
|
17
|
+
|
|
18
|
+
### Perguntas Essenciais
|
|
19
|
+
|
|
20
|
+
Quando receber uma feature request ambígua, faça estas perguntas:
|
|
21
|
+
|
|
22
|
+
1. **Quem?** - Qual o usuário/persona principal?
|
|
23
|
+
2. **O quê?** - O que exatamente deve acontecer?
|
|
24
|
+
3. **Por quê?** - Qual problema resolve? Qual o valor?
|
|
25
|
+
4. **Quando?** - Urgência? Deadline externo?
|
|
26
|
+
5. **Como medir?** - Como saberemos que funcionou?
|
|
27
|
+
|
|
28
|
+
### Template de User Story
|
|
29
|
+
|
|
30
|
+
```markdown
|
|
31
|
+
## User Story: {Nome da Feature}
|
|
32
|
+
|
|
33
|
+
**Como** {persona/usuário},
|
|
34
|
+
**Eu quero** {ação/funcionalidade},
|
|
35
|
+
**Para que** {benefício/valor}.
|
|
36
|
+
|
|
37
|
+
### Critérios de Aceitação
|
|
38
|
+
|
|
39
|
+
**Dado** {contexto inicial},
|
|
40
|
+
**Quando** {ação do usuário},
|
|
41
|
+
**Então** {resultado esperado}.
|
|
42
|
+
|
|
43
|
+
### Fora do Escopo
|
|
44
|
+
|
|
45
|
+
- {Item explicitamente excluído}
|
|
46
|
+
|
|
47
|
+
### Perguntas Pendentes
|
|
48
|
+
|
|
49
|
+
- [ ] {Dúvida não resolvida}
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Matriz de Priorização (RICE)
|
|
53
|
+
|
|
54
|
+
| Fator | Descrição | Escala |
|
|
55
|
+
|-------|-----------|--------|
|
|
56
|
+
| **R**each | Quantos usuários impacta | 1-10 |
|
|
57
|
+
| **I**mpact | Quanto impacta cada usuário | 0.25, 0.5, 1, 2, 3 |
|
|
58
|
+
| **C**onfidence | Confiança nas estimativas | 0-100% |
|
|
59
|
+
| **E**ffort | Pessoa-semanas de trabalho | 1+ |
|
|
60
|
+
|
|
61
|
+
```
|
|
62
|
+
RICE Score = (Reach × Impact × Confidence) / Effort
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### Exemplo
|
|
66
|
+
|
|
67
|
+
| Feature | Reach | Impact | Confidence | Effort | Score |
|
|
68
|
+
|---------|-------|--------|------------|--------|-------|
|
|
69
|
+
| Login social | 8 | 1 | 80% | 1 | 6.4 |
|
|
70
|
+
| Dashboard | 5 | 2 | 90% | 3 | 3.0 |
|
|
71
|
+
| Export PDF | 3 | 0.5 | 100% | 0.5 | 3.0 |
|
|
72
|
+
| Dark mode | 4 | 0.25 | 100% | 1 | 1.0 |
|
|
73
|
+
|
|
74
|
+
## MVP vs Nice-to-Have
|
|
75
|
+
|
|
76
|
+
### Critérios para MVP
|
|
77
|
+
|
|
78
|
+
1. **Resolve o problema core** do usuário
|
|
79
|
+
2. **Diferencia** da concorrência
|
|
80
|
+
3. **Validável** em 2-4 semanas
|
|
81
|
+
4. **Mensurável** (métricas definidas)
|
|
82
|
+
|
|
83
|
+
### Framework MoSCoW
|
|
84
|
+
|
|
85
|
+
| Categoria | Significado | Exemplo |
|
|
86
|
+
|-----------|-------------|---------|
|
|
87
|
+
| **M**ust have | Essencial, sem isso não funciona | Login, CRUD básico |
|
|
88
|
+
| **S**hould have | Importante, mas não crítico | Filtros avançados |
|
|
89
|
+
| **C**ould have | Desejável se houver tempo | Exportar relatório |
|
|
90
|
+
| **W**on't have | Fora deste release | Integração X |
|
|
91
|
+
|
|
92
|
+
## Estimativa de Esforço
|
|
93
|
+
|
|
94
|
+
### T-Shirt Sizing
|
|
95
|
+
|
|
96
|
+
| Size | Dias | Complexidade |
|
|
97
|
+
|------|------|--------------|
|
|
98
|
+
| XS | 0.5 | Task trivial |
|
|
99
|
+
| S | 1-2 | Feature simples |
|
|
100
|
+
| M | 3-5 | Feature com complexidade |
|
|
101
|
+
| L | 5-10 | Feature complexa |
|
|
102
|
+
| XL | 10+ | Épico, precisa quebrar |
|
|
103
|
+
|
|
104
|
+
### Fatores de Risco
|
|
105
|
+
|
|
106
|
+
Multiplicar estimativa por:
|
|
107
|
+
|
|
108
|
+
| Fator | Multiplicador |
|
|
109
|
+
|-------|---------------|
|
|
110
|
+
| Tecnologia nova | 1.5x |
|
|
111
|
+
| Integração externa | 1.3x |
|
|
112
|
+
| Requisitos vagos | 1.5x |
|
|
113
|
+
| Primeiro da equipe | 1.3x |
|
|
114
|
+
|
|
115
|
+
## Template de ADR (Architecture Decision Record)
|
|
116
|
+
|
|
117
|
+
```markdown
|
|
118
|
+
# ADR-{XXX}: {Título da Decisão}
|
|
119
|
+
|
|
120
|
+
## Status
|
|
121
|
+
{PROPOSED | ACCEPTED | DEPRECATED | SUPERSEDED}
|
|
122
|
+
|
|
123
|
+
## Contexto
|
|
124
|
+
{Situação que requer decisão}
|
|
125
|
+
|
|
126
|
+
## Opções Consideradas
|
|
127
|
+
|
|
128
|
+
### Opção 1: {Nome}
|
|
129
|
+
- Prós: ...
|
|
130
|
+
- Contras: ...
|
|
131
|
+
- Custo: ...
|
|
132
|
+
|
|
133
|
+
### Opção 2: {Nome}
|
|
134
|
+
- Prós: ...
|
|
135
|
+
- Contras: ...
|
|
136
|
+
- Custo: ...
|
|
137
|
+
|
|
138
|
+
## Decisão
|
|
139
|
+
{Opção escolhida e por quê}
|
|
140
|
+
|
|
141
|
+
## Consequências
|
|
142
|
+
- {Implicação positiva}
|
|
143
|
+
- {Implicação negativa}
|
|
144
|
+
- {Trade-off aceito}
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
## Cálculo de ROI
|
|
148
|
+
|
|
149
|
+
```markdown
|
|
150
|
+
## ROI Estimado: {Feature}
|
|
151
|
+
|
|
152
|
+
### Benefícios (anual)
|
|
153
|
+
- Aumento de conversão: R$ X
|
|
154
|
+
- Redução de suporte: R$ Y
|
|
155
|
+
- Economia de tempo: R$ Z
|
|
156
|
+
- **Total Benefícios**: R$ (X+Y+Z)
|
|
157
|
+
|
|
158
|
+
### Custos
|
|
159
|
+
- Desenvolvimento: R$ A (horas × rate)
|
|
160
|
+
- Infraestrutura: R$ B/mês × 12
|
|
161
|
+
- Manutenção: R$ C/ano
|
|
162
|
+
- **Total Custos**: R$ (A+B+C)
|
|
163
|
+
|
|
164
|
+
### ROI
|
|
165
|
+
**ROI = (Benefícios - Custos) / Custos × 100**
|
|
166
|
+
|
|
167
|
+
ROI = (X+Y+Z - A+B+C) / (A+B+C) × 100 = **{N}%**
|
|
168
|
+
|
|
169
|
+
### Payback
|
|
170
|
+
**Meses = Custo Inicial / (Benefício Mensal - Custo Mensal)**
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
## Red Flags em Requisitos
|
|
174
|
+
|
|
175
|
+
Alertar quando detectar:
|
|
176
|
+
|
|
177
|
+
- "Deve ser igual ao [concorrente X]" sem especificar
|
|
178
|
+
- "Simples" ou "rápido" sem estimativa
|
|
179
|
+
- "Usuários querem..." sem evidência
|
|
180
|
+
- Escopo crescente sem priorização
|
|
181
|
+
- Deadline impossível sem trade-offs
|
|
182
|
+
|
|
183
|
+
## Checklist de Requisitos
|
|
184
|
+
|
|
185
|
+
- [ ] Persona/usuário definido
|
|
186
|
+
- [ ] Problema claramente articulado
|
|
187
|
+
- [ ] Valor de negócio quantificado
|
|
188
|
+
- [ ] Critérios de aceitação escritos
|
|
189
|
+
- [ ] Fora do escopo explícito
|
|
190
|
+
- [ ] Dependências mapeadas
|
|
191
|
+
- [ ] Riscos identificados
|
|
192
|
+
- [ ] Estimativa de esforço
|
|
193
|
+
- [ ] Prioridade definida (RICE/MoSCoW)
|
|
194
|
+
|
|
195
|
+
---
|
|
196
|
+
|
|
197
|
+
*MORPH-SPEC by Polymorphism Tech*
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# Standards Architect
|
|
2
|
+
|
|
3
|
+
Especialista em padrões de código, arquitetura e boas práticas para projetos .NET.
|
|
4
|
+
|
|
5
|
+
## Responsabilidades
|
|
6
|
+
|
|
7
|
+
1. **Garantir aderência aos padrões** definidos em `.morph/standards/`
|
|
8
|
+
2. **Validar nomenclatura** de classes, métodos, variáveis
|
|
9
|
+
3. **Revisar código** antes de aprovar merges
|
|
10
|
+
4. **Definir convenções** de projeto
|
|
11
|
+
|
|
12
|
+
## Triggers
|
|
13
|
+
|
|
14
|
+
Ativado automaticamente em todo projeto MORPH-SPEC (Core Agent).
|
|
15
|
+
|
|
16
|
+
Keywords: `standards`, `naming`, `convention`, `pattern`, `review`, `quality`
|
|
17
|
+
|
|
18
|
+
## Padrões de Código (.NET)
|
|
19
|
+
|
|
20
|
+
### Nomenclatura
|
|
21
|
+
|
|
22
|
+
```csharp
|
|
23
|
+
// Classes: PascalCase
|
|
24
|
+
public class OrderService { }
|
|
25
|
+
|
|
26
|
+
// Interfaces: I + PascalCase
|
|
27
|
+
public interface IOrderService { }
|
|
28
|
+
|
|
29
|
+
// Métodos: PascalCase
|
|
30
|
+
public async Task<Order> GetOrderAsync(int id) { }
|
|
31
|
+
|
|
32
|
+
// Variáveis: camelCase
|
|
33
|
+
private readonly ILogger _logger;
|
|
34
|
+
|
|
35
|
+
// Constantes: UPPER_SNAKE_CASE
|
|
36
|
+
public const string DEFAULT_STATUS = "pending";
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### Estrutura de Projeto
|
|
40
|
+
|
|
41
|
+
```
|
|
42
|
+
src/
|
|
43
|
+
├── {Project}.Domain/ # Entidades, Value Objects
|
|
44
|
+
├── {Project}.Application/ # Services, DTOs, Interfaces
|
|
45
|
+
├── {Project}.Infrastructure/ # EF, External Services
|
|
46
|
+
├── {Project}.Web/ # Blazor, API Controllers
|
|
47
|
+
└── {Project}.Tests/ # Unit, Integration tests
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### Padrões Blazor
|
|
51
|
+
|
|
52
|
+
```razor
|
|
53
|
+
@* Componentes: PascalCase.razor *@
|
|
54
|
+
@* Parameters: [Parameter] obrigatório *@
|
|
55
|
+
@* EventCallbacks: On{Event}Async *@
|
|
56
|
+
|
|
57
|
+
<OrderList Orders="@_orders" OnSelectAsync="HandleSelectAsync" />
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## Documentação de Referência
|
|
61
|
+
|
|
62
|
+
- [C# Coding Conventions](https://learn.microsoft.com/en-us/dotnet/csharp/fundamentals/coding-style/coding-conventions)
|
|
63
|
+
- [.NET Naming Guidelines](https://learn.microsoft.com/en-us/dotnet/standard/design-guidelines/naming-guidelines)
|
|
64
|
+
- [Blazor Best Practices](https://learn.microsoft.com/en-us/aspnet/core/blazor/performance)
|
|
65
|
+
|
|
66
|
+
## Checklist de Revisão
|
|
67
|
+
|
|
68
|
+
- [ ] Nomenclatura segue convenções
|
|
69
|
+
- [ ] Async/await usado corretamente
|
|
70
|
+
- [ ] Nullable reference types habilitado
|
|
71
|
+
- [ ] DI registrado corretamente
|
|
72
|
+
- [ ] Logs estruturados com ILogger
|
|
73
|
+
- [ ] Exceptions tratadas adequadamente
|
|
74
|
+
- [ ] Código sem warnings
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
*MORPH-SPEC by Polymorphism Tech*
|
|
@@ -0,0 +1,325 @@
|
|
|
1
|
+
# UI/UX Designer
|
|
2
|
+
|
|
3
|
+
Especialista em design de interfaces, experiência do usuário e componentes Blazor avançados.
|
|
4
|
+
|
|
5
|
+
## Responsabilidades
|
|
6
|
+
|
|
7
|
+
1. **Projetar interfaces** intuitivas e acessíveis
|
|
8
|
+
2. **Criar componentes** Blazor reutilizáveis
|
|
9
|
+
3. **Implementar dashboards** e visualizações
|
|
10
|
+
4. **Garantir responsividade** e acessibilidade
|
|
11
|
+
|
|
12
|
+
## Triggers
|
|
13
|
+
|
|
14
|
+
Keywords: `wizard`, `dashboard`, `complex form`, `drag-drop`, `chart`, `ui`, `ux`, `design`, `layout`, `responsive`
|
|
15
|
+
|
|
16
|
+
## Princípios de Design
|
|
17
|
+
|
|
18
|
+
### Hierarquia Visual
|
|
19
|
+
|
|
20
|
+
1. **Títulos**: Grande, bold, alto contraste
|
|
21
|
+
2. **Conteúdo principal**: Tamanho médio, legível
|
|
22
|
+
3. **Informações secundárias**: Menor, cor mais suave
|
|
23
|
+
4. **Ações**: Botões destacados, CTAs claros
|
|
24
|
+
|
|
25
|
+
### Cores (Sistema)
|
|
26
|
+
|
|
27
|
+
```css
|
|
28
|
+
/* Tailwind/Bootstrap inspired */
|
|
29
|
+
--primary: #3b82f6; /* Ações principais */
|
|
30
|
+
--secondary: #6b7280; /* Ações secundárias */
|
|
31
|
+
--success: #10b981; /* Sucesso, confirmação */
|
|
32
|
+
--warning: #f59e0b; /* Alertas */
|
|
33
|
+
--danger: #ef4444; /* Erros, exclusão */
|
|
34
|
+
--info: #06b6d4; /* Informativo */
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### Espaçamento
|
|
38
|
+
|
|
39
|
+
```css
|
|
40
|
+
/* Sistema de 4px */
|
|
41
|
+
--space-1: 0.25rem; /* 4px */
|
|
42
|
+
--space-2: 0.5rem; /* 8px */
|
|
43
|
+
--space-3: 0.75rem; /* 12px */
|
|
44
|
+
--space-4: 1rem; /* 16px */
|
|
45
|
+
--space-6: 1.5rem; /* 24px */
|
|
46
|
+
--space-8: 2rem; /* 32px */
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Componentes Comuns
|
|
50
|
+
|
|
51
|
+
### Card
|
|
52
|
+
|
|
53
|
+
```razor
|
|
54
|
+
<!-- Components/Card.razor -->
|
|
55
|
+
<div class="bg-white rounded-lg shadow-md p-6 @Class">
|
|
56
|
+
@if (Title is not null)
|
|
57
|
+
{
|
|
58
|
+
<h3 class="text-lg font-semibold text-gray-900 mb-4">@Title</h3>
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
<div class="@BodyClass">
|
|
62
|
+
@ChildContent
|
|
63
|
+
</div>
|
|
64
|
+
|
|
65
|
+
@if (Footer is not null)
|
|
66
|
+
{
|
|
67
|
+
<div class="mt-4 pt-4 border-t border-gray-200">
|
|
68
|
+
@Footer
|
|
69
|
+
</div>
|
|
70
|
+
}
|
|
71
|
+
</div>
|
|
72
|
+
|
|
73
|
+
@code {
|
|
74
|
+
[Parameter] public string? Title { get; set; }
|
|
75
|
+
[Parameter] public RenderFragment? ChildContent { get; set; }
|
|
76
|
+
[Parameter] public RenderFragment? Footer { get; set; }
|
|
77
|
+
[Parameter] public string? Class { get; set; }
|
|
78
|
+
[Parameter] public string? BodyClass { get; set; }
|
|
79
|
+
}
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### Stat Card (Dashboard)
|
|
83
|
+
|
|
84
|
+
```razor
|
|
85
|
+
<!-- Components/StatCard.razor -->
|
|
86
|
+
<div class="bg-white rounded-lg shadow p-6">
|
|
87
|
+
<div class="flex items-center justify-between">
|
|
88
|
+
<div>
|
|
89
|
+
<p class="text-sm font-medium text-gray-600">@Label</p>
|
|
90
|
+
<p class="text-2xl font-bold text-gray-900">@Value</p>
|
|
91
|
+
@if (Change is not null)
|
|
92
|
+
{
|
|
93
|
+
<p class="text-sm @(IsPositive ? "text-green-600" : "text-red-600")">
|
|
94
|
+
@(IsPositive ? "+" : "")@Change
|
|
95
|
+
</p>
|
|
96
|
+
}
|
|
97
|
+
</div>
|
|
98
|
+
<div class="p-3 bg-@Color-100 rounded-full">
|
|
99
|
+
<Icon Name="@IconName" Class="w-6 h-6 text-@Color-600" />
|
|
100
|
+
</div>
|
|
101
|
+
</div>
|
|
102
|
+
</div>
|
|
103
|
+
|
|
104
|
+
@code {
|
|
105
|
+
[Parameter, EditorRequired] public string Label { get; set; } = "";
|
|
106
|
+
[Parameter, EditorRequired] public string Value { get; set; } = "";
|
|
107
|
+
[Parameter] public string? Change { get; set; }
|
|
108
|
+
[Parameter] public bool IsPositive { get; set; }
|
|
109
|
+
[Parameter] public string Color { get; set; } = "blue";
|
|
110
|
+
[Parameter] public string IconName { get; set; } = "chart-bar";
|
|
111
|
+
}
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
### Wizard/Stepper
|
|
115
|
+
|
|
116
|
+
```razor
|
|
117
|
+
<!-- Components/Wizard.razor -->
|
|
118
|
+
<div class="w-full">
|
|
119
|
+
<!-- Steps indicator -->
|
|
120
|
+
<div class="flex items-center justify-between mb-8">
|
|
121
|
+
@for (int i = 0; i < Steps.Count; i++)
|
|
122
|
+
{
|
|
123
|
+
var step = Steps[i];
|
|
124
|
+
var isCompleted = i < CurrentStep;
|
|
125
|
+
var isCurrent = i == CurrentStep;
|
|
126
|
+
|
|
127
|
+
<div class="flex items-center @(i < Steps.Count - 1 ? "flex-1" : "")">
|
|
128
|
+
<div class="flex items-center">
|
|
129
|
+
<span class="w-10 h-10 rounded-full flex items-center justify-center
|
|
130
|
+
@(isCompleted ? "bg-green-500 text-white" :
|
|
131
|
+
isCurrent ? "bg-blue-500 text-white" :
|
|
132
|
+
"bg-gray-200 text-gray-600")">
|
|
133
|
+
@if (isCompleted)
|
|
134
|
+
{
|
|
135
|
+
<Icon Name="check" Class="w-5 h-5" />
|
|
136
|
+
}
|
|
137
|
+
else
|
|
138
|
+
{
|
|
139
|
+
@(i + 1)
|
|
140
|
+
}
|
|
141
|
+
</span>
|
|
142
|
+
<span class="ml-2 text-sm font-medium
|
|
143
|
+
@(isCurrent ? "text-blue-600" : "text-gray-500")">
|
|
144
|
+
@step.Title
|
|
145
|
+
</span>
|
|
146
|
+
</div>
|
|
147
|
+
|
|
148
|
+
@if (i < Steps.Count - 1)
|
|
149
|
+
{
|
|
150
|
+
<div class="flex-1 h-1 mx-4 @(isCompleted ? "bg-green-500" : "bg-gray-200")">
|
|
151
|
+
</div>
|
|
152
|
+
}
|
|
153
|
+
</div>
|
|
154
|
+
}
|
|
155
|
+
</div>
|
|
156
|
+
|
|
157
|
+
<!-- Current step content -->
|
|
158
|
+
<div class="mb-8">
|
|
159
|
+
@Steps[CurrentStep].Content
|
|
160
|
+
</div>
|
|
161
|
+
|
|
162
|
+
<!-- Navigation -->
|
|
163
|
+
<div class="flex justify-between">
|
|
164
|
+
<button @onclick="Previous" disabled="@(CurrentStep == 0)"
|
|
165
|
+
class="px-4 py-2 text-gray-600 disabled:opacity-50">
|
|
166
|
+
Voltar
|
|
167
|
+
</button>
|
|
168
|
+
|
|
169
|
+
@if (CurrentStep < Steps.Count - 1)
|
|
170
|
+
{
|
|
171
|
+
<button @onclick="Next"
|
|
172
|
+
class="px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600">
|
|
173
|
+
Próximo
|
|
174
|
+
</button>
|
|
175
|
+
}
|
|
176
|
+
else
|
|
177
|
+
{
|
|
178
|
+
<button @onclick="Complete"
|
|
179
|
+
class="px-4 py-2 bg-green-500 text-white rounded hover:bg-green-600">
|
|
180
|
+
Concluir
|
|
181
|
+
</button>
|
|
182
|
+
}
|
|
183
|
+
</div>
|
|
184
|
+
</div>
|
|
185
|
+
|
|
186
|
+
@code {
|
|
187
|
+
[Parameter] public List<WizardStep> Steps { get; set; } = new();
|
|
188
|
+
[Parameter] public EventCallback OnComplete { get; set; }
|
|
189
|
+
|
|
190
|
+
private int CurrentStep { get; set; }
|
|
191
|
+
|
|
192
|
+
private void Next() => CurrentStep++;
|
|
193
|
+
private void Previous() => CurrentStep--;
|
|
194
|
+
private async Task Complete() => await OnComplete.InvokeAsync();
|
|
195
|
+
|
|
196
|
+
public record WizardStep(string Title, RenderFragment Content);
|
|
197
|
+
}
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
### Data Table
|
|
201
|
+
|
|
202
|
+
```razor
|
|
203
|
+
<!-- Components/DataTable.razor -->
|
|
204
|
+
@typeparam TItem
|
|
205
|
+
|
|
206
|
+
<div class="overflow-x-auto">
|
|
207
|
+
<table class="min-w-full divide-y divide-gray-200">
|
|
208
|
+
<thead class="bg-gray-50">
|
|
209
|
+
<tr>
|
|
210
|
+
@HeaderTemplate
|
|
211
|
+
</tr>
|
|
212
|
+
</thead>
|
|
213
|
+
<tbody class="bg-white divide-y divide-gray-200">
|
|
214
|
+
@if (Items is null || !Items.Any())
|
|
215
|
+
{
|
|
216
|
+
<tr>
|
|
217
|
+
<td colspan="100" class="px-6 py-4 text-center text-gray-500">
|
|
218
|
+
@EmptyMessage
|
|
219
|
+
</td>
|
|
220
|
+
</tr>
|
|
221
|
+
}
|
|
222
|
+
else
|
|
223
|
+
{
|
|
224
|
+
@foreach (var item in Items)
|
|
225
|
+
{
|
|
226
|
+
<tr class="hover:bg-gray-50">
|
|
227
|
+
@RowTemplate(item)
|
|
228
|
+
</tr>
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
</tbody>
|
|
232
|
+
</table>
|
|
233
|
+
</div>
|
|
234
|
+
|
|
235
|
+
@code {
|
|
236
|
+
[Parameter] public IEnumerable<TItem>? Items { get; set; }
|
|
237
|
+
[Parameter] public RenderFragment? HeaderTemplate { get; set; }
|
|
238
|
+
[Parameter] public RenderFragment<TItem> RowTemplate { get; set; } = default!;
|
|
239
|
+
[Parameter] public string EmptyMessage { get; set; } = "Nenhum registro encontrado.";
|
|
240
|
+
}
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
## Padrões de Layout
|
|
244
|
+
|
|
245
|
+
### Dashboard Layout
|
|
246
|
+
|
|
247
|
+
```razor
|
|
248
|
+
<div class="min-h-screen bg-gray-100">
|
|
249
|
+
<!-- Sidebar -->
|
|
250
|
+
<aside class="fixed inset-y-0 left-0 w-64 bg-white shadow-lg">
|
|
251
|
+
<!-- Sidebar content -->
|
|
252
|
+
</aside>
|
|
253
|
+
|
|
254
|
+
<!-- Main content -->
|
|
255
|
+
<main class="ml-64 p-8">
|
|
256
|
+
<!-- Header -->
|
|
257
|
+
<header class="mb-8">
|
|
258
|
+
<h1 class="text-2xl font-bold text-gray-900">Dashboard</h1>
|
|
259
|
+
</header>
|
|
260
|
+
|
|
261
|
+
<!-- Stats grid -->
|
|
262
|
+
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6 mb-8">
|
|
263
|
+
<StatCard Label="Vendas" Value="R$ 12.450" Change="+12%" IsPositive />
|
|
264
|
+
<!-- More stats -->
|
|
265
|
+
</div>
|
|
266
|
+
|
|
267
|
+
<!-- Content grid -->
|
|
268
|
+
<div class="grid grid-cols-1 lg:grid-cols-3 gap-6">
|
|
269
|
+
<Card Title="Pedidos Recentes" Class="lg:col-span-2">
|
|
270
|
+
<!-- Table -->
|
|
271
|
+
</Card>
|
|
272
|
+
<Card Title="Atividade">
|
|
273
|
+
<!-- Activity feed -->
|
|
274
|
+
</Card>
|
|
275
|
+
</div>
|
|
276
|
+
</main>
|
|
277
|
+
</div>
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
## Acessibilidade (A11y)
|
|
281
|
+
|
|
282
|
+
1. **Contraste**: Mínimo 4.5:1 para texto
|
|
283
|
+
2. **Focus visible**: Outline em elementos focáveis
|
|
284
|
+
3. **Labels**: Todo input com label associado
|
|
285
|
+
4. **ARIA**: Roles e labels onde necessário
|
|
286
|
+
5. **Keyboard nav**: Tab order lógico
|
|
287
|
+
|
|
288
|
+
```razor
|
|
289
|
+
<!-- Exemplo acessível -->
|
|
290
|
+
<label for="email" class="block text-sm font-medium text-gray-700">
|
|
291
|
+
Email
|
|
292
|
+
</label>
|
|
293
|
+
<input
|
|
294
|
+
id="email"
|
|
295
|
+
type="email"
|
|
296
|
+
aria-describedby="email-hint"
|
|
297
|
+
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm
|
|
298
|
+
focus:border-blue-500 focus:ring-blue-500" />
|
|
299
|
+
<p id="email-hint" class="mt-1 text-sm text-gray-500">
|
|
300
|
+
Usaremos para enviar atualizações.
|
|
301
|
+
</p>
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
## Documentação de Referência
|
|
305
|
+
|
|
306
|
+
- [Tailwind CSS](https://tailwindcss.com/docs)
|
|
307
|
+
- [Heroicons](https://heroicons.com/)
|
|
308
|
+
- [Blazor Components](https://learn.microsoft.com/en-us/aspnet/core/blazor/components/)
|
|
309
|
+
- [WCAG Guidelines](https://www.w3.org/WAI/WCAG21/quickref/)
|
|
310
|
+
|
|
311
|
+
## Checklist de UI
|
|
312
|
+
|
|
313
|
+
- [ ] Hierarquia visual clara
|
|
314
|
+
- [ ] Cores do sistema de design
|
|
315
|
+
- [ ] Espaçamento consistente (múltiplos de 4px)
|
|
316
|
+
- [ ] Responsivo (mobile-first)
|
|
317
|
+
- [ ] Estados: hover, focus, disabled, error
|
|
318
|
+
- [ ] Loading states (skeleton/spinner)
|
|
319
|
+
- [ ] Empty states informativos
|
|
320
|
+
- [ ] Mensagens de erro claras
|
|
321
|
+
- [ ] Acessibilidade básica (WCAG AA)
|
|
322
|
+
|
|
323
|
+
---
|
|
324
|
+
|
|
325
|
+
*MORPH-SPEC by Polymorphism Tech*
|