@polymorphism-tech/morph-spec 2.2.0 → 2.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.md +314 -1673
- package/LICENSE +72 -72
- package/README.md +515 -516
- package/bin/detect-agents.js +225 -225
- package/bin/morph-spec.js +358 -173
- package/bin/render-template.js +302 -302
- package/bin/semantic-detect-agents.js +246 -246
- package/bin/task-manager.js +429 -0
- package/bin/validate-agents-skills.js +251 -251
- package/bin/validate-agents.js +69 -69
- package/bin/validate-phase.js +263 -263
- package/bin/validate.js +369 -0
- package/content/.azure/README.md +293 -293
- package/content/.azure/docs/azure-devops-setup.md +454 -454
- package/content/.azure/docs/branch-strategy.md +398 -398
- package/content/.azure/docs/local-development.md +515 -515
- package/content/.azure/pipelines/pipeline-variables.yml +34 -34
- package/content/.azure/pipelines/prod-pipeline.yml +319 -319
- package/content/.azure/pipelines/staging-pipeline.yml +234 -234
- package/content/.azure/pipelines/templates/build-dotnet.yml +75 -75
- package/content/.azure/pipelines/templates/deploy-app-service.yml +94 -94
- package/content/.azure/pipelines/templates/deploy-container-app.yml +120 -120
- package/content/.azure/pipelines/templates/infra-deploy.yml +90 -90
- package/content/.claude/commands/morph-apply.md +221 -158
- package/content/.claude/commands/morph-archive.md +79 -79
- package/content/.claude/commands/morph-infra.md +209 -209
- package/content/.claude/commands/morph-preflight.md +227 -0
- package/content/.claude/commands/morph-proposal.md +122 -101
- package/content/.claude/commands/morph-status.md +86 -86
- package/content/.claude/commands/morph-troubleshoot.md +122 -0
- package/content/.claude/settings.local.json +15 -15
- package/content/.claude/skills/checklists/code-review.md +226 -0
- package/content/.claude/skills/checklists/morph-checklist.md +117 -0
- package/content/.claude/skills/checklists/simulation-checklist.md +77 -0
- package/content/.claude/skills/infra/bicep-architect.md +126 -419
- package/content/.claude/skills/infra/container-specialist.md +131 -437
- package/content/.claude/skills/infra/devops-engineer.md +119 -405
- package/content/.claude/skills/integrations/asaas-financial.md +130 -333
- package/content/.claude/skills/integrations/azure-identity.md +142 -309
- package/content/.claude/skills/integrations/clerk-auth.md +108 -290
- package/content/.claude/skills/integrations/resend-email.md +119 -0
- package/content/.claude/skills/specialists/ai-system-architect.md +192 -604
- package/content/.claude/skills/specialists/azure-architect.md +142 -142
- package/content/.claude/skills/specialists/code-analyzer.md +235 -0
- package/content/.claude/skills/specialists/dotnet-senior.md +287 -0
- package/content/.claude/skills/specialists/ef-modeler.md +113 -200
- package/content/.claude/skills/specialists/hangfire-orchestrator.md +126 -245
- package/content/.claude/skills/specialists/ms-agent-expert.md +109 -263
- package/content/.claude/skills/specialists/po-pm-advisor.md +197 -197
- package/content/.claude/skills/specialists/standards-architect.md +156 -78
- package/content/.claude/skills/specialists/testing-specialist.md +126 -0
- package/content/.claude/skills/specialists/ui-ux-designer.md +191 -1060
- package/content/.claude/skills/stacks/dotnet-blazor.md +210 -588
- package/content/.claude/skills/stacks/dotnet-nextjs.md +154 -402
- package/content/.claude/skills/workflows/morph-replicate.md +213 -0
- package/content/.claude/{commands/morph-clarify.md → skills/workflows/phase-clarify.md} +5 -58
- package/content/.claude/{commands/morph-design.md → skills/workflows/phase-design.md} +16 -86
- package/content/.claude/{commands/morph-setup.md → skills/workflows/phase-setup.md} +9 -17
- package/content/.claude/skills/workflows/phase-tasks.md +164 -0
- package/content/.claude/{commands/morph-uiux.md → skills/workflows/phase-uiux.md} +15 -88
- package/content/.morph/.morphversion +5 -5
- package/content/.morph/archive/.gitkeep +25 -25
- package/content/.morph/config/agents.json +378 -242
- package/content/.morph/config/config.template.json +89 -108
- package/content/.morph/docs/STORY-DRIVEN-DEVELOPMENT.md +392 -392
- package/content/.morph/docs/workflows/design-impl.md +37 -0
- package/content/.morph/docs/workflows/fast-track.md +29 -0
- package/content/.morph/docs/workflows/full-morph.md +76 -0
- package/content/.morph/docs/workflows/standard.md +44 -0
- package/content/.morph/docs/workflows/ui-refresh.md +39 -0
- package/content/.morph/examples/api-nextjs/README.md +241 -241
- package/content/.morph/examples/api-nextjs/contracts.ts +307 -307
- package/content/.morph/examples/api-nextjs/spec.md +399 -399
- package/content/.morph/examples/api-nextjs/tasks.md +168 -168
- package/content/.morph/examples/micro-saas/README.md +125 -125
- package/content/.morph/examples/micro-saas/contracts.cs +358 -358
- package/content/.morph/examples/micro-saas/decisions.md +246 -246
- package/content/.morph/examples/micro-saas/spec.md +236 -236
- package/content/.morph/examples/micro-saas/tasks.md +150 -150
- package/content/.morph/examples/multi-agent/README.md +309 -309
- package/content/.morph/examples/multi-agent/contracts.cs +433 -433
- package/content/.morph/examples/multi-agent/spec.md +479 -479
- package/content/.morph/examples/multi-agent/tasks.md +185 -185
- package/content/.morph/examples/scheduled-reports/decisions.md +158 -0
- package/content/.morph/examples/scheduled-reports/proposal.md +95 -0
- package/content/.morph/examples/scheduled-reports/spec.md +267 -0
- package/content/.morph/examples/state-v3.json +188 -0
- package/content/.morph/features/.gitkeep +25 -25
- package/content/.morph/hooks/README.md +190 -239
- package/content/.morph/hooks/pre-commit-agents.sh +24 -24
- package/content/.morph/hooks/pre-commit-all.sh +48 -48
- package/content/.morph/hooks/pre-commit-specs.sh +49 -49
- package/content/.morph/hooks/pre-commit-tests.sh +60 -60
- package/content/.morph/project.md +160 -160
- package/content/.morph/schemas/agent.schema.json +296 -296
- package/content/.morph/schemas/tasks.schema.json +220 -0
- package/content/.morph/specs/.gitkeep +20 -20
- package/content/.morph/standards/agent-framework-blazor-ui.md +359 -0
- package/content/.morph/standards/agent-framework-production.md +410 -0
- package/content/.morph/standards/agent-framework-setup.md +413 -453
- package/content/.morph/standards/agent-framework-workflows.md +349 -0
- package/content/.morph/standards/architecture.md +325 -325
- package/content/.morph/standards/azure.md +605 -379
- package/content/.morph/standards/coding.md +377 -377
- package/content/.morph/standards/dotnet10-migration.md +520 -494
- package/content/.morph/standards/fluent-ui-setup.md +590 -590
- package/content/.morph/standards/migration-guide.md +514 -514
- package/content/.morph/standards/passkeys-auth.md +423 -423
- package/content/.morph/standards/vector-search-rag.md +536 -536
- package/content/.morph/state.json +17 -17
- package/content/.morph/templates/FluentDesignTheme.cs +149 -149
- package/content/.morph/templates/MudTheme.cs +281 -281
- package/content/.morph/templates/agent.cs +163 -172
- package/content/.morph/templates/clarify-questions.md +159 -0
- package/content/.morph/templates/component.razor +239 -239
- package/content/.morph/templates/contracts/Commands.cs +74 -0
- package/content/.morph/templates/contracts/Entities.cs +25 -0
- package/content/.morph/templates/contracts/Queries.cs +74 -0
- package/content/.morph/templates/contracts/README.md +74 -0
- package/content/.morph/templates/contracts.cs +217 -217
- package/content/.morph/templates/decisions.md +123 -106
- package/content/.morph/templates/design-system.css +226 -226
- package/content/.morph/templates/infra/.dockerignore.example +89 -89
- package/content/.morph/templates/infra/Dockerfile.example +82 -82
- package/content/.morph/templates/infra/README.md +286 -286
- package/content/.morph/templates/infra/app-insights.bicep +63 -63
- package/content/.morph/templates/infra/app-service.bicep +164 -164
- package/content/.morph/templates/infra/container-app-env.bicep +49 -49
- package/content/.morph/templates/infra/container-app.bicep +156 -156
- package/content/.morph/templates/infra/deploy-checklist.md +426 -0
- package/content/.morph/templates/infra/deploy.ps1 +229 -229
- package/content/.morph/templates/infra/deploy.sh +208 -208
- package/content/.morph/templates/infra/key-vault.bicep +91 -91
- package/content/.morph/templates/infra/main.bicep +189 -189
- package/content/.morph/templates/infra/parameters.dev.json +29 -29
- package/content/.morph/templates/infra/parameters.prod.json +29 -29
- package/content/.morph/templates/infra/parameters.staging.json +29 -29
- package/content/.morph/templates/infra/sql-database.bicep +103 -103
- package/content/.morph/templates/infra/storage.bicep +106 -106
- package/content/.morph/templates/integrations/asaas-client.cs +387 -387
- package/content/.morph/templates/integrations/asaas-webhook.cs +351 -351
- package/content/.morph/templates/integrations/azure-identity-config.cs +288 -288
- package/content/.morph/templates/integrations/clerk-config.cs +258 -258
- package/content/.morph/templates/job.cs +171 -171
- package/content/.morph/templates/migration.cs +83 -83
- package/content/.morph/templates/proposal.md +141 -155
- package/content/.morph/templates/recap.md +94 -105
- package/content/.morph/templates/repository.cs +141 -141
- package/content/.morph/templates/saas/subscription.cs +347 -347
- package/content/.morph/templates/saas/tenant.cs +338 -338
- package/content/.morph/templates/service.cs +139 -139
- package/content/.morph/templates/simulation.md +353 -0
- package/content/.morph/templates/spec.md +149 -148
- package/content/.morph/templates/sprint-status.yaml +68 -68
- package/content/.morph/templates/state.template.json +222 -222
- package/content/.morph/templates/story.md +143 -143
- package/content/.morph/templates/tasks.md +257 -235
- package/content/.morph/templates/test.cs +239 -239
- package/content/.morph/templates/ui-components.md +362 -276
- package/content/.morph/templates/ui-design-system.md +286 -286
- package/content/.morph/templates/ui-flows.md +336 -336
- package/content/.morph/templates/ui-mockups.md +133 -133
- package/content/.morph/test-infra/example.bicep +59 -59
- package/content/CLAUDE.md +150 -442
- package/content/README.md +79 -79
- package/detectors/config-detector.js +223 -223
- package/detectors/conversation-analyzer.js +163 -163
- package/detectors/index.js +84 -84
- package/detectors/standards-generator.js +275 -275
- package/detectors/structure-detector.js +245 -250
- package/docs/README.md +144 -149
- package/docs/api/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.svg +977 -977
- package/docs/api/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.svg +1048 -1048
- package/docs/api/scripts/collapse.js +38 -38
- package/docs/api/scripts/commonNav.js +28 -28
- package/docs/api/scripts/linenumber.js +25 -25
- package/docs/api/scripts/nav.js +12 -12
- package/docs/api/scripts/polyfill.js +3 -3
- package/docs/api/scripts/prettify/Apache-License-2.0.txt +202 -202
- package/docs/api/scripts/prettify/lang-css.js +2 -2
- package/docs/api/scripts/prettify/prettify.js +28 -28
- package/docs/api/scripts/search.js +98 -98
- package/docs/api/styles/jsdoc.css +776 -776
- package/docs/api/styles/prettify.css +80 -80
- package/docs/examples.md +328 -328
- package/docs/getting-started.md +301 -302
- package/docs/installation.md +361 -361
- package/docs/templates.md +418 -418
- package/docs/validation-checklist.md +265 -266
- package/package.json +80 -80
- package/scripts/postinstall.js +132 -132
- package/src/commands/advance-phase.js +183 -0
- package/src/commands/analyze-blazor-concurrency.js +193 -0
- package/src/commands/create-story.js +351 -351
- package/src/commands/detect-agents.js +139 -0
- package/src/commands/detect.js +104 -104
- package/src/commands/doctor.js +356 -280
- package/src/commands/generate.js +149 -149
- package/src/commands/init.js +258 -245
- package/src/commands/lint-fluent.js +352 -0
- package/src/commands/rollback-phase.js +185 -0
- package/src/commands/session-summary.js +291 -0
- package/src/commands/shard-spec.js +224 -224
- package/src/commands/sprint-status.js +250 -250
- package/src/commands/state.js +333 -333
- package/src/commands/sync.js +167 -167
- package/src/commands/task.js +78 -0
- package/src/commands/troubleshoot.js +222 -0
- package/src/commands/update.js +192 -159
- package/src/commands/validate-blazor-state.js +210 -0
- package/src/commands/validate-blazor.js +156 -0
- package/src/commands/validate-css.js +84 -0
- package/src/commands/validate-phase.js +221 -0
- package/src/lib/blazor-concurrency-analyzer.js +288 -0
- package/src/lib/blazor-state-validator.js +291 -0
- package/src/lib/blazor-validator.js +374 -0
- package/src/lib/complexity-analyzer.js +441 -292
- package/src/lib/continuous-validator.js +421 -0
- package/src/lib/css-validator.js +352 -0
- package/src/lib/decision-constraint-loader.js +109 -0
- package/src/lib/design-system-generator.js +298 -298
- package/src/lib/learning-system.js +520 -0
- package/src/lib/mockup-generator.js +366 -0
- package/src/lib/recap-generator.js +205 -0
- package/src/lib/state-manager.js +397 -340
- package/src/lib/troubleshoot-grep.js +194 -0
- package/src/lib/troubleshoot-index.js +144 -0
- package/src/lib/ui-detector.js +350 -0
- package/src/lib/validation-runner.js +231 -0
- package/src/lib/validators/architecture-validator.js +387 -0
- package/src/lib/validators/contract-compliance-validator.js +273 -0
- package/src/lib/validators/package-validator.js +360 -0
- package/src/lib/validators/ui-contrast-validator.js +422 -0
- package/src/utils/file-copier.js +179 -139
- package/src/utils/logger.js +32 -32
- package/src/utils/version-checker.js +175 -175
- package/content/.claude/commands/morph-costs.md +0 -206
- package/content/.claude/commands/morph-tasks.md +0 -319
- package/content/.claude/skills/specialists/cost-guardian.md +0 -110
- package/content/.claude/skills/stacks/shopify.md +0 -445
- package/content/.morph/config/azure-pricing.json +0 -70
- package/content/.morph/config/azure-pricing.schema.json +0 -50
- package/content/.morph/hooks/pre-commit-costs.sh +0 -91
- package/docs/api/cost-calculator.js.html +0 -513
- package/docs/api/design-system-generator.js.html +0 -382
- package/docs/api/global.html +0 -5263
- package/docs/api/index.html +0 -96
- package/docs/api/state-manager.js.html +0 -423
- package/src/commands/cost.js +0 -181
- package/src/commands/update-pricing.js +0 -206
- package/src/lib/cost-calculator.js +0 -429
|
@@ -1,590 +1,590 @@
|
|
|
1
|
-
# Fluent UI Blazor - Setup e Padrões (.NET 10)
|
|
2
|
-
|
|
3
|
-
> Biblioteca de UI recomendada para projetos **AI-first** e micro-SaaS no MORPH-SPEC.
|
|
4
|
-
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
## 🎯 Por Que Fluent UI Blazor?
|
|
8
|
-
|
|
9
|
-
### Para Projetos AI-First
|
|
10
|
-
|
|
11
|
-
| Vantagem | Descrição |
|
|
12
|
-
|----------|-----------|
|
|
13
|
-
| **Componentes AI nativos** | Chat containers, streaming, typing indicators |
|
|
14
|
-
| **Microsoft Stack** | Integração perfeita com Agent Framework, Aspire, .NET 10 |
|
|
15
|
-
| **Design Copilot-like** | UX patterns da Microsoft para AI assistants |
|
|
16
|
-
| **Futuro-proof** | Microsoft evolui junto com AI capabilities |
|
|
17
|
-
| **Performance** | ~200KB gzipped (vs 500KB MudBlazor) |
|
|
18
|
-
| **Aspire Dashboard** | Mesma lib - consistência visual |
|
|
19
|
-
|
|
20
|
-
### Para Micro-SaaS
|
|
21
|
-
|
|
22
|
-
- **Design System moderno** - Microsoft 365 style
|
|
23
|
-
- **Acessibilidade nativa** - WCAG compliant
|
|
24
|
-
- **Dark mode** - Built-in
|
|
25
|
-
- **Responsive** - Mobile-first
|
|
26
|
-
- **Grátis** - MIT License, sem custos
|
|
27
|
-
|
|
28
|
-
---
|
|
29
|
-
|
|
30
|
-
## 📦 Setup
|
|
31
|
-
|
|
32
|
-
### 1. Instalar Package
|
|
33
|
-
|
|
34
|
-
```bash
|
|
35
|
-
dotnet add package Microsoft.FluentUI.AspNetCore.Components --version 4.0.0
|
|
36
|
-
```
|
|
37
|
-
|
|
38
|
-
### 2. Configurar Program.cs
|
|
39
|
-
|
|
40
|
-
```csharp
|
|
41
|
-
var builder = WebApplication.CreateBuilder(args);
|
|
42
|
-
|
|
43
|
-
// Blazor
|
|
44
|
-
builder.Services.AddRazorComponents()
|
|
45
|
-
.AddInteractiveServerComponents();
|
|
46
|
-
|
|
47
|
-
// Fluent UI
|
|
48
|
-
builder.Services.AddFluentUIComponents();
|
|
49
|
-
|
|
50
|
-
var app = builder.Build();
|
|
51
|
-
|
|
52
|
-
// Pipeline
|
|
53
|
-
app.UseStaticFiles();
|
|
54
|
-
app.UseAntiforgery();
|
|
55
|
-
|
|
56
|
-
app.MapRazorComponents<App>()
|
|
57
|
-
.AddInteractiveServerRenderMode()
|
|
58
|
-
.AddAdditionalAssemblies(typeof(Microsoft.FluentUI.AspNetCore.Components._Imports).Assembly);
|
|
59
|
-
|
|
60
|
-
app.Run();
|
|
61
|
-
```
|
|
62
|
-
|
|
63
|
-
### 3. Configurar _Imports.razor
|
|
64
|
-
|
|
65
|
-
```razor
|
|
66
|
-
@* Components/_Imports.razor *@
|
|
67
|
-
@using Microsoft.AspNetCore.Components.Web
|
|
68
|
-
@using Microsoft.FluentUI.AspNetCore.Components
|
|
69
|
-
@using Microsoft.FluentUI.AspNetCore.Components.Icons
|
|
70
|
-
```
|
|
71
|
-
|
|
72
|
-
### 4. Adicionar CSS e JS
|
|
73
|
-
|
|
74
|
-
```html
|
|
75
|
-
<!-- Components/App.razor -->
|
|
76
|
-
<!DOCTYPE html>
|
|
77
|
-
<html lang="pt-BR">
|
|
78
|
-
<head>
|
|
79
|
-
<meta charset="utf-8" />
|
|
80
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
81
|
-
<base href="/" />
|
|
82
|
-
|
|
83
|
-
<!-- Fluent UI CSS -->
|
|
84
|
-
<link href="_content/Microsoft.FluentUI.AspNetCore.Components/css/reboot.css" rel="stylesheet" />
|
|
85
|
-
<link href="_content/Microsoft.FluentUI.AspNetCore.Components/Microsoft.FluentUI.AspNetCore.Components.min.css" rel="stylesheet" />
|
|
86
|
-
|
|
87
|
-
<HeadOutlet />
|
|
88
|
-
</head>
|
|
89
|
-
<body>
|
|
90
|
-
<Routes />
|
|
91
|
-
|
|
92
|
-
<!-- Fluent UI JS -->
|
|
93
|
-
<script src="_content/Microsoft.FluentUI.AspNetCore.Components/Microsoft.FluentUI.AspNetCore.Components.lib.module.js" type="module"></script>
|
|
94
|
-
</body>
|
|
95
|
-
</html>
|
|
96
|
-
```
|
|
97
|
-
|
|
98
|
-
---
|
|
99
|
-
|
|
100
|
-
## 🎨 Layout SaaS Padrão
|
|
101
|
-
|
|
102
|
-
### Layout Principal
|
|
103
|
-
|
|
104
|
-
```razor
|
|
105
|
-
@* Components/Layout/MainLayout.razor *@
|
|
106
|
-
@inherits LayoutComponentBase
|
|
107
|
-
|
|
108
|
-
<FluentLayout>
|
|
109
|
-
<!-- Header -->
|
|
110
|
-
<FluentHeader>
|
|
111
|
-
<FluentStack Orientation="Orientation.Horizontal" HorizontalAlignment="HorizontalAlignment.SpaceBetween">
|
|
112
|
-
<FluentStack Orientation="Orientation.Horizontal">
|
|
113
|
-
<FluentIcon Value="@(new Icons.Regular.Size24.AppGeneric())" Color="Color.Accent" />
|
|
114
|
-
<FluentLabel Typo="Typography.H5">Meu SaaS</FluentLabel>
|
|
115
|
-
</FluentStack>
|
|
116
|
-
|
|
117
|
-
<FluentStack Orientation="Orientation.Horizontal">
|
|
118
|
-
<FluentButton Appearance="Appearance.Stealth" IconStart="@(new Icons.Regular.Size20.DarkTheme())">
|
|
119
|
-
Dark Mode
|
|
120
|
-
</FluentButton>
|
|
121
|
-
<FluentPersona Name="@_userName" Image="@_userAvatar" />
|
|
122
|
-
</FluentStack>
|
|
123
|
-
</FluentStack>
|
|
124
|
-
</FluentHeader>
|
|
125
|
-
|
|
126
|
-
<!-- Sidebar -->
|
|
127
|
-
<FluentNavMenu Width="250">
|
|
128
|
-
<FluentNavLink Icon="@(new Icons.Regular.Size20.Home())" Href="/" Match="NavLinkMatch.All">
|
|
129
|
-
Dashboard
|
|
130
|
-
</FluentNavLink>
|
|
131
|
-
<FluentNavLink Icon="@(new Icons.Regular.Size20.People())" Href="/customers">
|
|
132
|
-
Clientes
|
|
133
|
-
</FluentNavLink>
|
|
134
|
-
<FluentNavLink Icon="@(new Icons.Regular.Size20.Cart())" Href="/orders">
|
|
135
|
-
Pedidos
|
|
136
|
-
</FluentNavLink>
|
|
137
|
-
<FluentNavLink Icon="@(new Icons.Regular.Size20.Chat())" Href="/ai-assistant">
|
|
138
|
-
AI Assistant
|
|
139
|
-
</FluentNavLink>
|
|
140
|
-
|
|
141
|
-
<FluentDivider />
|
|
142
|
-
|
|
143
|
-
<FluentNavLink Icon="@(new Icons.Regular.Size20.Settings())" Href="/settings">
|
|
144
|
-
Configurações
|
|
145
|
-
</FluentNavLink>
|
|
146
|
-
</FluentNavMenu>
|
|
147
|
-
|
|
148
|
-
<!-- Main Content -->
|
|
149
|
-
<FluentMain>
|
|
150
|
-
<FluentBodyContent>
|
|
151
|
-
@Body
|
|
152
|
-
</FluentBodyContent>
|
|
153
|
-
</FluentMain>
|
|
154
|
-
</FluentLayout>
|
|
155
|
-
|
|
156
|
-
@code {
|
|
157
|
-
private string _userName = "Usuário";
|
|
158
|
-
private string _userAvatar = "";
|
|
159
|
-
}
|
|
160
|
-
```
|
|
161
|
-
|
|
162
|
-
---
|
|
163
|
-
|
|
164
|
-
## 📋 Componentes Essenciais
|
|
165
|
-
|
|
166
|
-
### Data Grid
|
|
167
|
-
|
|
168
|
-
```razor
|
|
169
|
-
@page "/customers"
|
|
170
|
-
|
|
171
|
-
<FluentStack Orientation="Orientation.Vertical">
|
|
172
|
-
<FluentStack Orientation="Orientation.Horizontal" HorizontalAlignment="HorizontalAlignment.SpaceBetween">
|
|
173
|
-
<FluentLabel Typo="Typography.H4">Clientes</FluentLabel>
|
|
174
|
-
<FluentButton Appearance="Appearance.Accent" IconStart="@(new Icons.Regular.Size20.Add())">
|
|
175
|
-
Novo Cliente
|
|
176
|
-
</FluentButton>
|
|
177
|
-
</FluentStack>
|
|
178
|
-
|
|
179
|
-
<FluentDataGrid Items="@_customers" GridTemplateColumns="1fr 2fr 2fr 1fr">
|
|
180
|
-
<PropertyColumn Property="@(c => c.Id)" />
|
|
181
|
-
<PropertyColumn Property="@(c => c.Name)" Title="Nome" />
|
|
182
|
-
<PropertyColumn Property="@(c => c.Email)" />
|
|
183
|
-
<TemplateColumn Title="Ações">
|
|
184
|
-
<FluentButton Appearance="Appearance.Stealth" IconStart="@(new Icons.Regular.Size16.Edit())">
|
|
185
|
-
Editar
|
|
186
|
-
</FluentButton>
|
|
187
|
-
</TemplateColumn>
|
|
188
|
-
</FluentDataGrid>
|
|
189
|
-
</FluentStack>
|
|
190
|
-
|
|
191
|
-
@code {
|
|
192
|
-
private IQueryable<Customer> _customers = new List<Customer>
|
|
193
|
-
{
|
|
194
|
-
new() { Id = 1, Name = "João Silva", Email = "joao@example.com" },
|
|
195
|
-
new() { Id = 2, Name = "Maria Santos", Email = "maria@example.com" }
|
|
196
|
-
}.AsQueryable();
|
|
197
|
-
}
|
|
198
|
-
```
|
|
199
|
-
|
|
200
|
-
### Formulários
|
|
201
|
-
|
|
202
|
-
```razor
|
|
203
|
-
@page "/customers/new"
|
|
204
|
-
|
|
205
|
-
<EditForm Model="@_model" OnValidSubmit="HandleSubmit">
|
|
206
|
-
<DataAnnotationsValidator />
|
|
207
|
-
|
|
208
|
-
<FluentStack Orientation="Orientation.Vertical">
|
|
209
|
-
<FluentLabel Typo="Typography.H4">Novo Cliente</FluentLabel>
|
|
210
|
-
|
|
211
|
-
<FluentTextField @bind-Value="_model.Name" Label="Nome" Required />
|
|
212
|
-
<FluentValidationMessage For="@(() => _model.Name)" />
|
|
213
|
-
|
|
214
|
-
<FluentTextField @bind-Value="_model.Email" Label="Email" TextFieldType="TextFieldType.Email" Required />
|
|
215
|
-
<FluentValidationMessage For="@(() => _model.Email)" />
|
|
216
|
-
|
|
217
|
-
<FluentTextField @bind-Value="_model.Phone" Label="Telefone" />
|
|
218
|
-
|
|
219
|
-
<FluentStack Orientation="Orientation.Horizontal">
|
|
220
|
-
<FluentButton Type="ButtonType.Submit" Appearance="Appearance.Accent">
|
|
221
|
-
Salvar
|
|
222
|
-
</FluentButton>
|
|
223
|
-
<FluentButton Appearance="Appearance.Neutral" OnClick="Cancel">
|
|
224
|
-
Cancelar
|
|
225
|
-
</FluentButton>
|
|
226
|
-
</FluentStack>
|
|
227
|
-
</FluentStack>
|
|
228
|
-
</EditForm>
|
|
229
|
-
|
|
230
|
-
@code {
|
|
231
|
-
private CustomerFormModel _model = new();
|
|
232
|
-
|
|
233
|
-
private async Task HandleSubmit()
|
|
234
|
-
{
|
|
235
|
-
// Salvar cliente
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
private void Cancel() => NavigationManager.NavigateTo("/customers");
|
|
239
|
-
}
|
|
240
|
-
```
|
|
241
|
-
|
|
242
|
-
### Dialogs e Mensagens
|
|
243
|
-
|
|
244
|
-
```razor
|
|
245
|
-
@inject IDialogService DialogService
|
|
246
|
-
@inject IMessageService MessageService
|
|
247
|
-
|
|
248
|
-
<FluentButton OnClick="ShowDialog">Abrir Dialog</FluentButton>
|
|
249
|
-
<FluentButton OnClick="ShowMessage">Mostrar Mensagem</FluentButton>
|
|
250
|
-
|
|
251
|
-
@code {
|
|
252
|
-
private async Task ShowDialog()
|
|
253
|
-
{
|
|
254
|
-
var dialog = await DialogService.ShowDialogAsync<ConfirmDialog>(new DialogParameters
|
|
255
|
-
{
|
|
256
|
-
Title = "Confirmar ação",
|
|
257
|
-
PrimaryAction = "Confirmar",
|
|
258
|
-
SecondaryAction = "Cancelar"
|
|
259
|
-
});
|
|
260
|
-
|
|
261
|
-
var result = await dialog.Result;
|
|
262
|
-
if (!result.Cancelled)
|
|
263
|
-
{
|
|
264
|
-
// Ação confirmada
|
|
265
|
-
}
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
private void ShowMessage()
|
|
269
|
-
{
|
|
270
|
-
MessageService.ShowMessageBar(options =>
|
|
271
|
-
{
|
|
272
|
-
options.Intent = MessageIntent.Success;
|
|
273
|
-
options.Title = "Sucesso!";
|
|
274
|
-
options.Body = "Operação realizada com sucesso.";
|
|
275
|
-
});
|
|
276
|
-
}
|
|
277
|
-
}
|
|
278
|
-
```
|
|
279
|
-
|
|
280
|
-
---
|
|
281
|
-
|
|
282
|
-
## 🤖 Componentes AI-Specific
|
|
283
|
-
|
|
284
|
-
### Chat Container
|
|
285
|
-
|
|
286
|
-
```razor
|
|
287
|
-
@page "/ai-assistant"
|
|
288
|
-
@inject IDocumentAssistantAgent Assistant
|
|
289
|
-
|
|
290
|
-
<FluentStack Orientation="Orientation.Vertical" Style="height: 100vh;">
|
|
291
|
-
<FluentLabel Typo="Typography.H4">AI Assistant</FluentLabel>
|
|
292
|
-
|
|
293
|
-
<!-- Messages Area -->
|
|
294
|
-
<FluentScrollArea Style="flex: 1; overflow-y: auto;">
|
|
295
|
-
<FluentStack Orientation="Orientation.Vertical">
|
|
296
|
-
@foreach (var message in _messages)
|
|
297
|
-
{
|
|
298
|
-
<FluentMessageBar Intent="@(message.IsUser ? MessageIntent.Info : MessageIntent.Success)">
|
|
299
|
-
<FluentLabel Weight="FontWeight.Bold">
|
|
300
|
-
@(message.IsUser ? "Você" : "AI Assistant")
|
|
301
|
-
</FluentLabel>
|
|
302
|
-
<FluentLabel>@message.Content</FluentLabel>
|
|
303
|
-
</FluentMessageBar>
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
@if (_isTyping)
|
|
307
|
-
{
|
|
308
|
-
<FluentProgress />
|
|
309
|
-
<FluentLabel Typo="Typography.Caption">AI está digitando...</FluentLabel>
|
|
310
|
-
}
|
|
311
|
-
</FluentStack>
|
|
312
|
-
</FluentScrollArea>
|
|
313
|
-
|
|
314
|
-
<!-- Input Area -->
|
|
315
|
-
<FluentStack Orientation="Orientation.Horizontal">
|
|
316
|
-
<FluentTextField @bind-Value="_userInput"
|
|
317
|
-
Placeholder="Digite sua pergunta..."
|
|
318
|
-
Style="flex: 1;"
|
|
319
|
-
@onkeypress="HandleKeyPress" />
|
|
320
|
-
<FluentButton Appearance="Appearance.Accent"
|
|
321
|
-
IconStart="@(new Icons.Regular.Size20.Send())"
|
|
322
|
-
OnClick="SendMessage"
|
|
323
|
-
Disabled="@_isTyping">
|
|
324
|
-
Enviar
|
|
325
|
-
</FluentButton>
|
|
326
|
-
</FluentStack>
|
|
327
|
-
</FluentStack>
|
|
328
|
-
|
|
329
|
-
@code {
|
|
330
|
-
private List<ChatMessage> _messages = new();
|
|
331
|
-
private string _userInput = "";
|
|
332
|
-
private bool _isTyping;
|
|
333
|
-
|
|
334
|
-
private async Task SendMessage()
|
|
335
|
-
{
|
|
336
|
-
if (string.IsNullOrWhiteSpace(_userInput)) return;
|
|
337
|
-
|
|
338
|
-
// Adicionar mensagem do usuário
|
|
339
|
-
_messages.Add(new ChatMessage { Content = _userInput, IsUser = true });
|
|
340
|
-
var question = _userInput;
|
|
341
|
-
_userInput = "";
|
|
342
|
-
_isTyping = true;
|
|
343
|
-
|
|
344
|
-
// Obter resposta do AI
|
|
345
|
-
var response = await Assistant.AskQuestionAsync(question);
|
|
346
|
-
_messages.Add(new ChatMessage { Content = response, IsUser = false });
|
|
347
|
-
|
|
348
|
-
_isTyping = false;
|
|
349
|
-
}
|
|
350
|
-
|
|
351
|
-
private async Task HandleKeyPress(KeyboardEventArgs e)
|
|
352
|
-
{
|
|
353
|
-
if (e.Key == "Enter" && !e.ShiftKey)
|
|
354
|
-
{
|
|
355
|
-
await SendMessage();
|
|
356
|
-
}
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
public class ChatMessage
|
|
360
|
-
{
|
|
361
|
-
public string Content { get; set; } = "";
|
|
362
|
-
public bool IsUser { get; set; }
|
|
363
|
-
}
|
|
364
|
-
}
|
|
365
|
-
```
|
|
366
|
-
|
|
367
|
-
### Streaming Response
|
|
368
|
-
|
|
369
|
-
```razor
|
|
370
|
-
@page "/ai-stream"
|
|
371
|
-
|
|
372
|
-
<FluentStack Orientation="Orientation.Vertical">
|
|
373
|
-
<FluentTextField @bind-Value="_prompt" Label="Prompt" />
|
|
374
|
-
<FluentButton OnClick="GenerateStream">Gerar (Streaming)</FluentButton>
|
|
375
|
-
|
|
376
|
-
<FluentCard>
|
|
377
|
-
<FluentLabel>@_streamedContent</FluentLabel>
|
|
378
|
-
@if (_isStreaming)
|
|
379
|
-
{
|
|
380
|
-
<FluentProgressRing />
|
|
381
|
-
}
|
|
382
|
-
</FluentCard>
|
|
383
|
-
</FluentStack>
|
|
384
|
-
|
|
385
|
-
@code {
|
|
386
|
-
private string _prompt = "";
|
|
387
|
-
private string _streamedContent = "";
|
|
388
|
-
private bool _isStreaming;
|
|
389
|
-
|
|
390
|
-
private async Task GenerateStream()
|
|
391
|
-
{
|
|
392
|
-
_streamedContent = "";
|
|
393
|
-
_isStreaming = true;
|
|
394
|
-
|
|
395
|
-
// Simular streaming (substituir com Agent Framework real)
|
|
396
|
-
var words = "Esta é uma resposta simulada do AI assistant em streaming.".Split(' ');
|
|
397
|
-
foreach (var word in words)
|
|
398
|
-
{
|
|
399
|
-
_streamedContent += word + " ";
|
|
400
|
-
StateHasChanged();
|
|
401
|
-
await Task.Delay(200);
|
|
402
|
-
}
|
|
403
|
-
|
|
404
|
-
_isStreaming = false;
|
|
405
|
-
}
|
|
406
|
-
}
|
|
407
|
-
```
|
|
408
|
-
|
|
409
|
-
---
|
|
410
|
-
|
|
411
|
-
## 🎨 Temas e Dark Mode
|
|
412
|
-
|
|
413
|
-
### Configurar Theme Provider
|
|
414
|
-
|
|
415
|
-
```razor
|
|
416
|
-
<!-- App.razor -->
|
|
417
|
-
<FluentDesignTheme @bind-Mode="@_theme"
|
|
418
|
-
StorageName="theme-preference"
|
|
419
|
-
OfficeColor="OfficeColor.Default" />
|
|
420
|
-
|
|
421
|
-
<FluentLayout>
|
|
422
|
-
<!-- Conteúdo -->
|
|
423
|
-
</FluentLayout>
|
|
424
|
-
|
|
425
|
-
@code {
|
|
426
|
-
private DesignThemeModes _theme = DesignThemeModes.System;
|
|
427
|
-
}
|
|
428
|
-
```
|
|
429
|
-
|
|
430
|
-
### Toggle Dark Mode
|
|
431
|
-
|
|
432
|
-
```razor
|
|
433
|
-
<FluentSwitch @bind-Value="_isDarkMode"
|
|
434
|
-
@bind-Value:after="ToggleTheme"
|
|
435
|
-
Label="@(_isDarkMode ? "Dark Mode" : "Light Mode")" />
|
|
436
|
-
|
|
437
|
-
@code {
|
|
438
|
-
private bool _isDarkMode;
|
|
439
|
-
|
|
440
|
-
private void ToggleTheme()
|
|
441
|
-
{
|
|
442
|
-
_theme = _isDarkMode ? DesignThemeModes.Dark : DesignThemeModes.Light;
|
|
443
|
-
}
|
|
444
|
-
}
|
|
445
|
-
```
|
|
446
|
-
|
|
447
|
-
---
|
|
448
|
-
|
|
449
|
-
## 🔄 Abordagem Híbrida (Fluent UI + MudBlazor)
|
|
450
|
-
|
|
451
|
-
### Quando Adicionar MudBlazor
|
|
452
|
-
|
|
453
|
-
Use MudBlazor para:
|
|
454
|
-
- **DataGrid complexo** - filtros avançados, agrupamento, export
|
|
455
|
-
- **Charts** - MudChart para dashboards analytics
|
|
456
|
-
- **Calendar/Scheduler** - se precisar de componentes avançados
|
|
457
|
-
|
|
458
|
-
### Setup Híbrido
|
|
459
|
-
|
|
460
|
-
```bash
|
|
461
|
-
dotnet add package Microsoft.FluentUI.AspNetCore.Components
|
|
462
|
-
dotnet add package MudBlazor
|
|
463
|
-
```
|
|
464
|
-
|
|
465
|
-
```csharp
|
|
466
|
-
// Program.cs
|
|
467
|
-
builder.Services.AddFluentUIComponents();
|
|
468
|
-
builder.Services.AddMudServices();
|
|
469
|
-
```
|
|
470
|
-
|
|
471
|
-
```html
|
|
472
|
-
<!-- App.razor -->
|
|
473
|
-
<!-- Fluent UI CSS -->
|
|
474
|
-
<link href="_content/Microsoft.FluentUI.AspNetCore.Components/Microsoft.FluentUI.AspNetCore.Components.min.css" rel="stylesheet" />
|
|
475
|
-
|
|
476
|
-
<!-- MudBlazor CSS -->
|
|
477
|
-
<link href="_content/MudBlazor/MudBlazor.min.css" rel="stylesheet" />
|
|
478
|
-
```
|
|
479
|
-
|
|
480
|
-
### Exemplo de Uso Combinado
|
|
481
|
-
|
|
482
|
-
```razor
|
|
483
|
-
@* Layout com Fluent UI *@
|
|
484
|
-
<FluentLayout>
|
|
485
|
-
<FluentHeader>...</FluentHeader>
|
|
486
|
-
|
|
487
|
-
<FluentMain>
|
|
488
|
-
@* Grid complexo com MudBlazor *@
|
|
489
|
-
<MudDataGrid T="Order"
|
|
490
|
-
Items="@_orders"
|
|
491
|
-
Filterable="true"
|
|
492
|
-
Groupable="true"
|
|
493
|
-
Dense="true">
|
|
494
|
-
<Columns>
|
|
495
|
-
<PropertyColumn Property="x => x.OrderNumber" Title="Número" />
|
|
496
|
-
<PropertyColumn Property="x => x.Total" Title="Total" Format="C2" />
|
|
497
|
-
</Columns>
|
|
498
|
-
</MudDataGrid>
|
|
499
|
-
|
|
500
|
-
@* Chat com Fluent UI *@
|
|
501
|
-
<FluentMessageBar Intent="MessageIntent.Success">
|
|
502
|
-
Pedido criado com sucesso!
|
|
503
|
-
</FluentMessageBar>
|
|
504
|
-
</FluentMain>
|
|
505
|
-
</FluentLayout>
|
|
506
|
-
```
|
|
507
|
-
|
|
508
|
-
---
|
|
509
|
-
|
|
510
|
-
## 📊 Performance Tips
|
|
511
|
-
|
|
512
|
-
### Bundle Size
|
|
513
|
-
|
|
514
|
-
```xml
|
|
515
|
-
<!-- .csproj -->
|
|
516
|
-
<PropertyGroup>
|
|
517
|
-
<!-- Trimming para reduzir bundle -->
|
|
518
|
-
<PublishTrimmed>true</PublishTrimmed>
|
|
519
|
-
<TrimMode>link</TrimMode>
|
|
520
|
-
</PropertyGroup>
|
|
521
|
-
```
|
|
522
|
-
|
|
523
|
-
### Lazy Loading de Componentes
|
|
524
|
-
|
|
525
|
-
```razor
|
|
526
|
-
@* Carregar MudBlazor só quando necessário *@
|
|
527
|
-
@if (_showComplexGrid)
|
|
528
|
-
{
|
|
529
|
-
<MudDataGrid ... />
|
|
530
|
-
}
|
|
531
|
-
else
|
|
532
|
-
{
|
|
533
|
-
<FluentDataGrid ... />
|
|
534
|
-
}
|
|
535
|
-
```
|
|
536
|
-
|
|
537
|
-
---
|
|
538
|
-
|
|
539
|
-
## ✅ Checklist de Implementação
|
|
540
|
-
|
|
541
|
-
- [ ] Package `Microsoft.FluentUI.AspNetCore.Components` instalado
|
|
542
|
-
- [ ] `AddFluentUIComponents()` no Program.cs
|
|
543
|
-
- [ ] CSS e JS referenciados no App.razor
|
|
544
|
-
- [ ] _Imports.razor atualizado
|
|
545
|
-
- [ ] Layout principal criado com FluentLayout
|
|
546
|
-
- [ ] Navegação configurada com FluentNavMenu
|
|
547
|
-
- [ ] Theme provider configurado
|
|
548
|
-
- [ ] Dark mode funcional
|
|
549
|
-
- [ ] Componentes AI (chat) implementados se aplicável
|
|
550
|
-
- [ ] (Opcional) MudBlazor adicionado para grids/charts complexos
|
|
551
|
-
|
|
552
|
-
---
|
|
553
|
-
|
|
554
|
-
## 🚫 O Que NÃO Fazer
|
|
555
|
-
|
|
556
|
-
❌ Misturar estilos - use Fluent UI OU MudBlazor consistentemente
|
|
557
|
-
❌ Importar todas as libs sem necessidade (bundle size)
|
|
558
|
-
❌ Ignorar acessibilidade (Fluent UI tem nativa)
|
|
559
|
-
❌ Criar componentes customizados sem checar se já existem
|
|
560
|
-
❌ Usar JavaScript customizado (Fluent UI tem tudo em C#)
|
|
561
|
-
|
|
562
|
-
---
|
|
563
|
-
|
|
564
|
-
## 📚 Recursos
|
|
565
|
-
|
|
566
|
-
| Recurso | URL |
|
|
567
|
-
|---------|-----|
|
|
568
|
-
| Documentação Oficial | [fluentui-blazor.net](https://www.fluentui-blazor.net/) |
|
|
569
|
-
| GitHub | [github.com/microsoft/fluentui-blazor](https://github.com/microsoft/fluentui-blazor) |
|
|
570
|
-
| Exemplos | [fluentui-blazor.net/examples](https://www.fluentui-blazor.net/examples) |
|
|
571
|
-
| Icons Explorer | [fluentui-blazor.net/icon-explorer](https://www.fluentui-blazor.net/icon-explorer) |
|
|
572
|
-
| MudBlazor (complemento) | [mudblazor.com](https://mudblazor.com/) |
|
|
573
|
-
|
|
574
|
-
---
|
|
575
|
-
|
|
576
|
-
## 🎓 Comparativo Rápido
|
|
577
|
-
|
|
578
|
-
| Feature | Fluent UI | MudBlazor | Recomendação |
|
|
579
|
-
|---------|-----------|-----------|--------------|
|
|
580
|
-
| AI Components | ✅ Nativo | ❌ Não | **Fluent UI** |
|
|
581
|
-
| DataGrid | ⚠️ Básico | ✅ Avançado | **MudBlazor** |
|
|
582
|
-
| Charts | ❌ Não | ✅ Sim | **MudBlazor** |
|
|
583
|
-
| Performance | ✅ Leve | ⚠️ Pesado | **Fluent UI** |
|
|
584
|
-
| Microsoft Integration | ✅ Nativo | ❌ Não | **Fluent UI** |
|
|
585
|
-
| Templates Prontos | ⚠️ Poucos | ✅ Muitos | **MudBlazor** |
|
|
586
|
-
| Futuro AI | ✅ Garantido | ❓ Incerto | **Fluent UI** |
|
|
587
|
-
|
|
588
|
-
---
|
|
589
|
-
|
|
590
|
-
*MORPH-SPEC by Polymorphism Tech*
|
|
1
|
+
# Fluent UI Blazor - Setup e Padrões (.NET 10)
|
|
2
|
+
|
|
3
|
+
> Biblioteca de UI recomendada para projetos **AI-first** e micro-SaaS no MORPH-SPEC.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 🎯 Por Que Fluent UI Blazor?
|
|
8
|
+
|
|
9
|
+
### Para Projetos AI-First
|
|
10
|
+
|
|
11
|
+
| Vantagem | Descrição |
|
|
12
|
+
|----------|-----------|
|
|
13
|
+
| **Componentes AI nativos** | Chat containers, streaming, typing indicators |
|
|
14
|
+
| **Microsoft Stack** | Integração perfeita com Agent Framework, Aspire, .NET 10 |
|
|
15
|
+
| **Design Copilot-like** | UX patterns da Microsoft para AI assistants |
|
|
16
|
+
| **Futuro-proof** | Microsoft evolui junto com AI capabilities |
|
|
17
|
+
| **Performance** | ~200KB gzipped (vs 500KB MudBlazor) |
|
|
18
|
+
| **Aspire Dashboard** | Mesma lib - consistência visual |
|
|
19
|
+
|
|
20
|
+
### Para Micro-SaaS
|
|
21
|
+
|
|
22
|
+
- **Design System moderno** - Microsoft 365 style
|
|
23
|
+
- **Acessibilidade nativa** - WCAG compliant
|
|
24
|
+
- **Dark mode** - Built-in
|
|
25
|
+
- **Responsive** - Mobile-first
|
|
26
|
+
- **Grátis** - MIT License, sem custos
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## 📦 Setup
|
|
31
|
+
|
|
32
|
+
### 1. Instalar Package
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
dotnet add package Microsoft.FluentUI.AspNetCore.Components --version 4.0.0
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### 2. Configurar Program.cs
|
|
39
|
+
|
|
40
|
+
```csharp
|
|
41
|
+
var builder = WebApplication.CreateBuilder(args);
|
|
42
|
+
|
|
43
|
+
// Blazor
|
|
44
|
+
builder.Services.AddRazorComponents()
|
|
45
|
+
.AddInteractiveServerComponents();
|
|
46
|
+
|
|
47
|
+
// Fluent UI
|
|
48
|
+
builder.Services.AddFluentUIComponents();
|
|
49
|
+
|
|
50
|
+
var app = builder.Build();
|
|
51
|
+
|
|
52
|
+
// Pipeline
|
|
53
|
+
app.UseStaticFiles();
|
|
54
|
+
app.UseAntiforgery();
|
|
55
|
+
|
|
56
|
+
app.MapRazorComponents<App>()
|
|
57
|
+
.AddInteractiveServerRenderMode()
|
|
58
|
+
.AddAdditionalAssemblies(typeof(Microsoft.FluentUI.AspNetCore.Components._Imports).Assembly);
|
|
59
|
+
|
|
60
|
+
app.Run();
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### 3. Configurar _Imports.razor
|
|
64
|
+
|
|
65
|
+
```razor
|
|
66
|
+
@* Components/_Imports.razor *@
|
|
67
|
+
@using Microsoft.AspNetCore.Components.Web
|
|
68
|
+
@using Microsoft.FluentUI.AspNetCore.Components
|
|
69
|
+
@using Microsoft.FluentUI.AspNetCore.Components.Icons
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### 4. Adicionar CSS e JS
|
|
73
|
+
|
|
74
|
+
```html
|
|
75
|
+
<!-- Components/App.razor -->
|
|
76
|
+
<!DOCTYPE html>
|
|
77
|
+
<html lang="pt-BR">
|
|
78
|
+
<head>
|
|
79
|
+
<meta charset="utf-8" />
|
|
80
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
81
|
+
<base href="/" />
|
|
82
|
+
|
|
83
|
+
<!-- Fluent UI CSS -->
|
|
84
|
+
<link href="_content/Microsoft.FluentUI.AspNetCore.Components/css/reboot.css" rel="stylesheet" />
|
|
85
|
+
<link href="_content/Microsoft.FluentUI.AspNetCore.Components/Microsoft.FluentUI.AspNetCore.Components.min.css" rel="stylesheet" />
|
|
86
|
+
|
|
87
|
+
<HeadOutlet />
|
|
88
|
+
</head>
|
|
89
|
+
<body>
|
|
90
|
+
<Routes />
|
|
91
|
+
|
|
92
|
+
<!-- Fluent UI JS -->
|
|
93
|
+
<script src="_content/Microsoft.FluentUI.AspNetCore.Components/Microsoft.FluentUI.AspNetCore.Components.lib.module.js" type="module"></script>
|
|
94
|
+
</body>
|
|
95
|
+
</html>
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
---
|
|
99
|
+
|
|
100
|
+
## 🎨 Layout SaaS Padrão
|
|
101
|
+
|
|
102
|
+
### Layout Principal
|
|
103
|
+
|
|
104
|
+
```razor
|
|
105
|
+
@* Components/Layout/MainLayout.razor *@
|
|
106
|
+
@inherits LayoutComponentBase
|
|
107
|
+
|
|
108
|
+
<FluentLayout>
|
|
109
|
+
<!-- Header -->
|
|
110
|
+
<FluentHeader>
|
|
111
|
+
<FluentStack Orientation="Orientation.Horizontal" HorizontalAlignment="HorizontalAlignment.SpaceBetween">
|
|
112
|
+
<FluentStack Orientation="Orientation.Horizontal">
|
|
113
|
+
<FluentIcon Value="@(new Icons.Regular.Size24.AppGeneric())" Color="Color.Accent" />
|
|
114
|
+
<FluentLabel Typo="Typography.H5">Meu SaaS</FluentLabel>
|
|
115
|
+
</FluentStack>
|
|
116
|
+
|
|
117
|
+
<FluentStack Orientation="Orientation.Horizontal">
|
|
118
|
+
<FluentButton Appearance="Appearance.Stealth" IconStart="@(new Icons.Regular.Size20.DarkTheme())">
|
|
119
|
+
Dark Mode
|
|
120
|
+
</FluentButton>
|
|
121
|
+
<FluentPersona Name="@_userName" Image="@_userAvatar" />
|
|
122
|
+
</FluentStack>
|
|
123
|
+
</FluentStack>
|
|
124
|
+
</FluentHeader>
|
|
125
|
+
|
|
126
|
+
<!-- Sidebar -->
|
|
127
|
+
<FluentNavMenu Width="250">
|
|
128
|
+
<FluentNavLink Icon="@(new Icons.Regular.Size20.Home())" Href="/" Match="NavLinkMatch.All">
|
|
129
|
+
Dashboard
|
|
130
|
+
</FluentNavLink>
|
|
131
|
+
<FluentNavLink Icon="@(new Icons.Regular.Size20.People())" Href="/customers">
|
|
132
|
+
Clientes
|
|
133
|
+
</FluentNavLink>
|
|
134
|
+
<FluentNavLink Icon="@(new Icons.Regular.Size20.Cart())" Href="/orders">
|
|
135
|
+
Pedidos
|
|
136
|
+
</FluentNavLink>
|
|
137
|
+
<FluentNavLink Icon="@(new Icons.Regular.Size20.Chat())" Href="/ai-assistant">
|
|
138
|
+
AI Assistant
|
|
139
|
+
</FluentNavLink>
|
|
140
|
+
|
|
141
|
+
<FluentDivider />
|
|
142
|
+
|
|
143
|
+
<FluentNavLink Icon="@(new Icons.Regular.Size20.Settings())" Href="/settings">
|
|
144
|
+
Configurações
|
|
145
|
+
</FluentNavLink>
|
|
146
|
+
</FluentNavMenu>
|
|
147
|
+
|
|
148
|
+
<!-- Main Content -->
|
|
149
|
+
<FluentMain>
|
|
150
|
+
<FluentBodyContent>
|
|
151
|
+
@Body
|
|
152
|
+
</FluentBodyContent>
|
|
153
|
+
</FluentMain>
|
|
154
|
+
</FluentLayout>
|
|
155
|
+
|
|
156
|
+
@code {
|
|
157
|
+
private string _userName = "Usuário";
|
|
158
|
+
private string _userAvatar = "";
|
|
159
|
+
}
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
---
|
|
163
|
+
|
|
164
|
+
## 📋 Componentes Essenciais
|
|
165
|
+
|
|
166
|
+
### Data Grid
|
|
167
|
+
|
|
168
|
+
```razor
|
|
169
|
+
@page "/customers"
|
|
170
|
+
|
|
171
|
+
<FluentStack Orientation="Orientation.Vertical">
|
|
172
|
+
<FluentStack Orientation="Orientation.Horizontal" HorizontalAlignment="HorizontalAlignment.SpaceBetween">
|
|
173
|
+
<FluentLabel Typo="Typography.H4">Clientes</FluentLabel>
|
|
174
|
+
<FluentButton Appearance="Appearance.Accent" IconStart="@(new Icons.Regular.Size20.Add())">
|
|
175
|
+
Novo Cliente
|
|
176
|
+
</FluentButton>
|
|
177
|
+
</FluentStack>
|
|
178
|
+
|
|
179
|
+
<FluentDataGrid Items="@_customers" GridTemplateColumns="1fr 2fr 2fr 1fr">
|
|
180
|
+
<PropertyColumn Property="@(c => c.Id)" />
|
|
181
|
+
<PropertyColumn Property="@(c => c.Name)" Title="Nome" />
|
|
182
|
+
<PropertyColumn Property="@(c => c.Email)" />
|
|
183
|
+
<TemplateColumn Title="Ações">
|
|
184
|
+
<FluentButton Appearance="Appearance.Stealth" IconStart="@(new Icons.Regular.Size16.Edit())">
|
|
185
|
+
Editar
|
|
186
|
+
</FluentButton>
|
|
187
|
+
</TemplateColumn>
|
|
188
|
+
</FluentDataGrid>
|
|
189
|
+
</FluentStack>
|
|
190
|
+
|
|
191
|
+
@code {
|
|
192
|
+
private IQueryable<Customer> _customers = new List<Customer>
|
|
193
|
+
{
|
|
194
|
+
new() { Id = 1, Name = "João Silva", Email = "joao@example.com" },
|
|
195
|
+
new() { Id = 2, Name = "Maria Santos", Email = "maria@example.com" }
|
|
196
|
+
}.AsQueryable();
|
|
197
|
+
}
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
### Formulários
|
|
201
|
+
|
|
202
|
+
```razor
|
|
203
|
+
@page "/customers/new"
|
|
204
|
+
|
|
205
|
+
<EditForm Model="@_model" OnValidSubmit="HandleSubmit">
|
|
206
|
+
<DataAnnotationsValidator />
|
|
207
|
+
|
|
208
|
+
<FluentStack Orientation="Orientation.Vertical">
|
|
209
|
+
<FluentLabel Typo="Typography.H4">Novo Cliente</FluentLabel>
|
|
210
|
+
|
|
211
|
+
<FluentTextField @bind-Value="_model.Name" Label="Nome" Required />
|
|
212
|
+
<FluentValidationMessage For="@(() => _model.Name)" />
|
|
213
|
+
|
|
214
|
+
<FluentTextField @bind-Value="_model.Email" Label="Email" TextFieldType="TextFieldType.Email" Required />
|
|
215
|
+
<FluentValidationMessage For="@(() => _model.Email)" />
|
|
216
|
+
|
|
217
|
+
<FluentTextField @bind-Value="_model.Phone" Label="Telefone" />
|
|
218
|
+
|
|
219
|
+
<FluentStack Orientation="Orientation.Horizontal">
|
|
220
|
+
<FluentButton Type="ButtonType.Submit" Appearance="Appearance.Accent">
|
|
221
|
+
Salvar
|
|
222
|
+
</FluentButton>
|
|
223
|
+
<FluentButton Appearance="Appearance.Neutral" OnClick="Cancel">
|
|
224
|
+
Cancelar
|
|
225
|
+
</FluentButton>
|
|
226
|
+
</FluentStack>
|
|
227
|
+
</FluentStack>
|
|
228
|
+
</EditForm>
|
|
229
|
+
|
|
230
|
+
@code {
|
|
231
|
+
private CustomerFormModel _model = new();
|
|
232
|
+
|
|
233
|
+
private async Task HandleSubmit()
|
|
234
|
+
{
|
|
235
|
+
// Salvar cliente
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
private void Cancel() => NavigationManager.NavigateTo("/customers");
|
|
239
|
+
}
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
### Dialogs e Mensagens
|
|
243
|
+
|
|
244
|
+
```razor
|
|
245
|
+
@inject IDialogService DialogService
|
|
246
|
+
@inject IMessageService MessageService
|
|
247
|
+
|
|
248
|
+
<FluentButton OnClick="ShowDialog">Abrir Dialog</FluentButton>
|
|
249
|
+
<FluentButton OnClick="ShowMessage">Mostrar Mensagem</FluentButton>
|
|
250
|
+
|
|
251
|
+
@code {
|
|
252
|
+
private async Task ShowDialog()
|
|
253
|
+
{
|
|
254
|
+
var dialog = await DialogService.ShowDialogAsync<ConfirmDialog>(new DialogParameters
|
|
255
|
+
{
|
|
256
|
+
Title = "Confirmar ação",
|
|
257
|
+
PrimaryAction = "Confirmar",
|
|
258
|
+
SecondaryAction = "Cancelar"
|
|
259
|
+
});
|
|
260
|
+
|
|
261
|
+
var result = await dialog.Result;
|
|
262
|
+
if (!result.Cancelled)
|
|
263
|
+
{
|
|
264
|
+
// Ação confirmada
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
private void ShowMessage()
|
|
269
|
+
{
|
|
270
|
+
MessageService.ShowMessageBar(options =>
|
|
271
|
+
{
|
|
272
|
+
options.Intent = MessageIntent.Success;
|
|
273
|
+
options.Title = "Sucesso!";
|
|
274
|
+
options.Body = "Operação realizada com sucesso.";
|
|
275
|
+
});
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
---
|
|
281
|
+
|
|
282
|
+
## 🤖 Componentes AI-Specific
|
|
283
|
+
|
|
284
|
+
### Chat Container
|
|
285
|
+
|
|
286
|
+
```razor
|
|
287
|
+
@page "/ai-assistant"
|
|
288
|
+
@inject IDocumentAssistantAgent Assistant
|
|
289
|
+
|
|
290
|
+
<FluentStack Orientation="Orientation.Vertical" Style="height: 100vh;">
|
|
291
|
+
<FluentLabel Typo="Typography.H4">AI Assistant</FluentLabel>
|
|
292
|
+
|
|
293
|
+
<!-- Messages Area -->
|
|
294
|
+
<FluentScrollArea Style="flex: 1; overflow-y: auto;">
|
|
295
|
+
<FluentStack Orientation="Orientation.Vertical">
|
|
296
|
+
@foreach (var message in _messages)
|
|
297
|
+
{
|
|
298
|
+
<FluentMessageBar Intent="@(message.IsUser ? MessageIntent.Info : MessageIntent.Success)">
|
|
299
|
+
<FluentLabel Weight="FontWeight.Bold">
|
|
300
|
+
@(message.IsUser ? "Você" : "AI Assistant")
|
|
301
|
+
</FluentLabel>
|
|
302
|
+
<FluentLabel>@message.Content</FluentLabel>
|
|
303
|
+
</FluentMessageBar>
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
@if (_isTyping)
|
|
307
|
+
{
|
|
308
|
+
<FluentProgress />
|
|
309
|
+
<FluentLabel Typo="Typography.Caption">AI está digitando...</FluentLabel>
|
|
310
|
+
}
|
|
311
|
+
</FluentStack>
|
|
312
|
+
</FluentScrollArea>
|
|
313
|
+
|
|
314
|
+
<!-- Input Area -->
|
|
315
|
+
<FluentStack Orientation="Orientation.Horizontal">
|
|
316
|
+
<FluentTextField @bind-Value="_userInput"
|
|
317
|
+
Placeholder="Digite sua pergunta..."
|
|
318
|
+
Style="flex: 1;"
|
|
319
|
+
@onkeypress="HandleKeyPress" />
|
|
320
|
+
<FluentButton Appearance="Appearance.Accent"
|
|
321
|
+
IconStart="@(new Icons.Regular.Size20.Send())"
|
|
322
|
+
OnClick="SendMessage"
|
|
323
|
+
Disabled="@_isTyping">
|
|
324
|
+
Enviar
|
|
325
|
+
</FluentButton>
|
|
326
|
+
</FluentStack>
|
|
327
|
+
</FluentStack>
|
|
328
|
+
|
|
329
|
+
@code {
|
|
330
|
+
private List<ChatMessage> _messages = new();
|
|
331
|
+
private string _userInput = "";
|
|
332
|
+
private bool _isTyping;
|
|
333
|
+
|
|
334
|
+
private async Task SendMessage()
|
|
335
|
+
{
|
|
336
|
+
if (string.IsNullOrWhiteSpace(_userInput)) return;
|
|
337
|
+
|
|
338
|
+
// Adicionar mensagem do usuário
|
|
339
|
+
_messages.Add(new ChatMessage { Content = _userInput, IsUser = true });
|
|
340
|
+
var question = _userInput;
|
|
341
|
+
_userInput = "";
|
|
342
|
+
_isTyping = true;
|
|
343
|
+
|
|
344
|
+
// Obter resposta do AI
|
|
345
|
+
var response = await Assistant.AskQuestionAsync(question);
|
|
346
|
+
_messages.Add(new ChatMessage { Content = response, IsUser = false });
|
|
347
|
+
|
|
348
|
+
_isTyping = false;
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
private async Task HandleKeyPress(KeyboardEventArgs e)
|
|
352
|
+
{
|
|
353
|
+
if (e.Key == "Enter" && !e.ShiftKey)
|
|
354
|
+
{
|
|
355
|
+
await SendMessage();
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
public class ChatMessage
|
|
360
|
+
{
|
|
361
|
+
public string Content { get; set; } = "";
|
|
362
|
+
public bool IsUser { get; set; }
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
### Streaming Response
|
|
368
|
+
|
|
369
|
+
```razor
|
|
370
|
+
@page "/ai-stream"
|
|
371
|
+
|
|
372
|
+
<FluentStack Orientation="Orientation.Vertical">
|
|
373
|
+
<FluentTextField @bind-Value="_prompt" Label="Prompt" />
|
|
374
|
+
<FluentButton OnClick="GenerateStream">Gerar (Streaming)</FluentButton>
|
|
375
|
+
|
|
376
|
+
<FluentCard>
|
|
377
|
+
<FluentLabel>@_streamedContent</FluentLabel>
|
|
378
|
+
@if (_isStreaming)
|
|
379
|
+
{
|
|
380
|
+
<FluentProgressRing />
|
|
381
|
+
}
|
|
382
|
+
</FluentCard>
|
|
383
|
+
</FluentStack>
|
|
384
|
+
|
|
385
|
+
@code {
|
|
386
|
+
private string _prompt = "";
|
|
387
|
+
private string _streamedContent = "";
|
|
388
|
+
private bool _isStreaming;
|
|
389
|
+
|
|
390
|
+
private async Task GenerateStream()
|
|
391
|
+
{
|
|
392
|
+
_streamedContent = "";
|
|
393
|
+
_isStreaming = true;
|
|
394
|
+
|
|
395
|
+
// Simular streaming (substituir com Agent Framework real)
|
|
396
|
+
var words = "Esta é uma resposta simulada do AI assistant em streaming.".Split(' ');
|
|
397
|
+
foreach (var word in words)
|
|
398
|
+
{
|
|
399
|
+
_streamedContent += word + " ";
|
|
400
|
+
StateHasChanged();
|
|
401
|
+
await Task.Delay(200);
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
_isStreaming = false;
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
```
|
|
408
|
+
|
|
409
|
+
---
|
|
410
|
+
|
|
411
|
+
## 🎨 Temas e Dark Mode
|
|
412
|
+
|
|
413
|
+
### Configurar Theme Provider
|
|
414
|
+
|
|
415
|
+
```razor
|
|
416
|
+
<!-- App.razor -->
|
|
417
|
+
<FluentDesignTheme @bind-Mode="@_theme"
|
|
418
|
+
StorageName="theme-preference"
|
|
419
|
+
OfficeColor="OfficeColor.Default" />
|
|
420
|
+
|
|
421
|
+
<FluentLayout>
|
|
422
|
+
<!-- Conteúdo -->
|
|
423
|
+
</FluentLayout>
|
|
424
|
+
|
|
425
|
+
@code {
|
|
426
|
+
private DesignThemeModes _theme = DesignThemeModes.System;
|
|
427
|
+
}
|
|
428
|
+
```
|
|
429
|
+
|
|
430
|
+
### Toggle Dark Mode
|
|
431
|
+
|
|
432
|
+
```razor
|
|
433
|
+
<FluentSwitch @bind-Value="_isDarkMode"
|
|
434
|
+
@bind-Value:after="ToggleTheme"
|
|
435
|
+
Label="@(_isDarkMode ? "Dark Mode" : "Light Mode")" />
|
|
436
|
+
|
|
437
|
+
@code {
|
|
438
|
+
private bool _isDarkMode;
|
|
439
|
+
|
|
440
|
+
private void ToggleTheme()
|
|
441
|
+
{
|
|
442
|
+
_theme = _isDarkMode ? DesignThemeModes.Dark : DesignThemeModes.Light;
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
```
|
|
446
|
+
|
|
447
|
+
---
|
|
448
|
+
|
|
449
|
+
## 🔄 Abordagem Híbrida (Fluent UI + MudBlazor)
|
|
450
|
+
|
|
451
|
+
### Quando Adicionar MudBlazor
|
|
452
|
+
|
|
453
|
+
Use MudBlazor para:
|
|
454
|
+
- **DataGrid complexo** - filtros avançados, agrupamento, export
|
|
455
|
+
- **Charts** - MudChart para dashboards analytics
|
|
456
|
+
- **Calendar/Scheduler** - se precisar de componentes avançados
|
|
457
|
+
|
|
458
|
+
### Setup Híbrido
|
|
459
|
+
|
|
460
|
+
```bash
|
|
461
|
+
dotnet add package Microsoft.FluentUI.AspNetCore.Components
|
|
462
|
+
dotnet add package MudBlazor
|
|
463
|
+
```
|
|
464
|
+
|
|
465
|
+
```csharp
|
|
466
|
+
// Program.cs
|
|
467
|
+
builder.Services.AddFluentUIComponents();
|
|
468
|
+
builder.Services.AddMudServices();
|
|
469
|
+
```
|
|
470
|
+
|
|
471
|
+
```html
|
|
472
|
+
<!-- App.razor -->
|
|
473
|
+
<!-- Fluent UI CSS -->
|
|
474
|
+
<link href="_content/Microsoft.FluentUI.AspNetCore.Components/Microsoft.FluentUI.AspNetCore.Components.min.css" rel="stylesheet" />
|
|
475
|
+
|
|
476
|
+
<!-- MudBlazor CSS -->
|
|
477
|
+
<link href="_content/MudBlazor/MudBlazor.min.css" rel="stylesheet" />
|
|
478
|
+
```
|
|
479
|
+
|
|
480
|
+
### Exemplo de Uso Combinado
|
|
481
|
+
|
|
482
|
+
```razor
|
|
483
|
+
@* Layout com Fluent UI *@
|
|
484
|
+
<FluentLayout>
|
|
485
|
+
<FluentHeader>...</FluentHeader>
|
|
486
|
+
|
|
487
|
+
<FluentMain>
|
|
488
|
+
@* Grid complexo com MudBlazor *@
|
|
489
|
+
<MudDataGrid T="Order"
|
|
490
|
+
Items="@_orders"
|
|
491
|
+
Filterable="true"
|
|
492
|
+
Groupable="true"
|
|
493
|
+
Dense="true">
|
|
494
|
+
<Columns>
|
|
495
|
+
<PropertyColumn Property="x => x.OrderNumber" Title="Número" />
|
|
496
|
+
<PropertyColumn Property="x => x.Total" Title="Total" Format="C2" />
|
|
497
|
+
</Columns>
|
|
498
|
+
</MudDataGrid>
|
|
499
|
+
|
|
500
|
+
@* Chat com Fluent UI *@
|
|
501
|
+
<FluentMessageBar Intent="MessageIntent.Success">
|
|
502
|
+
Pedido criado com sucesso!
|
|
503
|
+
</FluentMessageBar>
|
|
504
|
+
</FluentMain>
|
|
505
|
+
</FluentLayout>
|
|
506
|
+
```
|
|
507
|
+
|
|
508
|
+
---
|
|
509
|
+
|
|
510
|
+
## 📊 Performance Tips
|
|
511
|
+
|
|
512
|
+
### Bundle Size
|
|
513
|
+
|
|
514
|
+
```xml
|
|
515
|
+
<!-- .csproj -->
|
|
516
|
+
<PropertyGroup>
|
|
517
|
+
<!-- Trimming para reduzir bundle -->
|
|
518
|
+
<PublishTrimmed>true</PublishTrimmed>
|
|
519
|
+
<TrimMode>link</TrimMode>
|
|
520
|
+
</PropertyGroup>
|
|
521
|
+
```
|
|
522
|
+
|
|
523
|
+
### Lazy Loading de Componentes
|
|
524
|
+
|
|
525
|
+
```razor
|
|
526
|
+
@* Carregar MudBlazor só quando necessário *@
|
|
527
|
+
@if (_showComplexGrid)
|
|
528
|
+
{
|
|
529
|
+
<MudDataGrid ... />
|
|
530
|
+
}
|
|
531
|
+
else
|
|
532
|
+
{
|
|
533
|
+
<FluentDataGrid ... />
|
|
534
|
+
}
|
|
535
|
+
```
|
|
536
|
+
|
|
537
|
+
---
|
|
538
|
+
|
|
539
|
+
## ✅ Checklist de Implementação
|
|
540
|
+
|
|
541
|
+
- [ ] Package `Microsoft.FluentUI.AspNetCore.Components` instalado
|
|
542
|
+
- [ ] `AddFluentUIComponents()` no Program.cs
|
|
543
|
+
- [ ] CSS e JS referenciados no App.razor
|
|
544
|
+
- [ ] _Imports.razor atualizado
|
|
545
|
+
- [ ] Layout principal criado com FluentLayout
|
|
546
|
+
- [ ] Navegação configurada com FluentNavMenu
|
|
547
|
+
- [ ] Theme provider configurado
|
|
548
|
+
- [ ] Dark mode funcional
|
|
549
|
+
- [ ] Componentes AI (chat) implementados se aplicável
|
|
550
|
+
- [ ] (Opcional) MudBlazor adicionado para grids/charts complexos
|
|
551
|
+
|
|
552
|
+
---
|
|
553
|
+
|
|
554
|
+
## 🚫 O Que NÃO Fazer
|
|
555
|
+
|
|
556
|
+
❌ Misturar estilos - use Fluent UI OU MudBlazor consistentemente
|
|
557
|
+
❌ Importar todas as libs sem necessidade (bundle size)
|
|
558
|
+
❌ Ignorar acessibilidade (Fluent UI tem nativa)
|
|
559
|
+
❌ Criar componentes customizados sem checar se já existem
|
|
560
|
+
❌ Usar JavaScript customizado (Fluent UI tem tudo em C#)
|
|
561
|
+
|
|
562
|
+
---
|
|
563
|
+
|
|
564
|
+
## 📚 Recursos
|
|
565
|
+
|
|
566
|
+
| Recurso | URL |
|
|
567
|
+
|---------|-----|
|
|
568
|
+
| Documentação Oficial | [fluentui-blazor.net](https://www.fluentui-blazor.net/) |
|
|
569
|
+
| GitHub | [github.com/microsoft/fluentui-blazor](https://github.com/microsoft/fluentui-blazor) |
|
|
570
|
+
| Exemplos | [fluentui-blazor.net/examples](https://www.fluentui-blazor.net/examples) |
|
|
571
|
+
| Icons Explorer | [fluentui-blazor.net/icon-explorer](https://www.fluentui-blazor.net/icon-explorer) |
|
|
572
|
+
| MudBlazor (complemento) | [mudblazor.com](https://mudblazor.com/) |
|
|
573
|
+
|
|
574
|
+
---
|
|
575
|
+
|
|
576
|
+
## 🎓 Comparativo Rápido
|
|
577
|
+
|
|
578
|
+
| Feature | Fluent UI | MudBlazor | Recomendação |
|
|
579
|
+
|---------|-----------|-----------|--------------|
|
|
580
|
+
| AI Components | ✅ Nativo | ❌ Não | **Fluent UI** |
|
|
581
|
+
| DataGrid | ⚠️ Básico | ✅ Avançado | **MudBlazor** |
|
|
582
|
+
| Charts | ❌ Não | ✅ Sim | **MudBlazor** |
|
|
583
|
+
| Performance | ✅ Leve | ⚠️ Pesado | **Fluent UI** |
|
|
584
|
+
| Microsoft Integration | ✅ Nativo | ❌ Não | **Fluent UI** |
|
|
585
|
+
| Templates Prontos | ⚠️ Poucos | ✅ Muitos | **MudBlazor** |
|
|
586
|
+
| Futuro AI | ✅ Garantido | ❓ Incerto | **Fluent UI** |
|
|
587
|
+
|
|
588
|
+
---
|
|
589
|
+
|
|
590
|
+
*MORPH-SPEC by Polymorphism Tech*
|