Skills per mudBlazor
This commit is contained in:
@@ -0,0 +1,163 @@
|
||||
---
|
||||
name: blazor
|
||||
description: |
|
||||
Builds Blazor WASM components for admin and main UI applications.
|
||||
Use when: Creating/modifying Razor components, configuring render modes, implementing authentication, managing component state, or working with MudBlazor components.
|
||||
allowed-tools: Read, Edit, Write, Glob, Grep, Bash, mcp__context7__resolve-library-id, mcp__context7__query-docs
|
||||
---
|
||||
|
||||
# Blazor Skill
|
||||
|
||||
Sorcha uses Blazor with hybrid rendering (Server + WebAssembly). The Admin UI (`src/Apps/Sorcha.Admin/`) runs behind YARP API Gateway. Components use MudBlazor for UI and support three render modes: static server, interactive server, and interactive WASM.
|
||||
|
||||
## Quick Start
|
||||
|
||||
### Render Mode Selection
|
||||
|
||||
```razor
|
||||
@* WASM - Complex interactive pages (Designer, Diagrams) *@
|
||||
@page "/designer"
|
||||
@rendermode InteractiveWebAssembly
|
||||
@attribute [Authorize]
|
||||
|
||||
@* Server - Admin pages needing real-time SignalR *@
|
||||
@page "/admin/audit"
|
||||
@rendermode @(new InteractiveServerRenderMode(prerender: false))
|
||||
@attribute [Authorize(Roles = "Administrator")]
|
||||
|
||||
@* Static - Public pages (Login) - no @rendermode directive *@
|
||||
@page "/login"
|
||||
@attribute [AllowAnonymous]
|
||||
```
|
||||
|
||||
### Component with Loading State
|
||||
|
||||
```razor
|
||||
@inject HttpClient Http
|
||||
|
||||
<MudPaper Elevation="2" Class="pa-4">
|
||||
@if (_isLoading && !_hasLoadedOnce)
|
||||
{
|
||||
<MudProgressCircular Indeterminate="true" Size="Size.Small" />
|
||||
}
|
||||
else if (_data != null)
|
||||
{
|
||||
<MudText>@_data.Title</MudText>
|
||||
}
|
||||
else if (_errorMessage != null)
|
||||
{
|
||||
<MudAlert Severity="Severity.Error">@_errorMessage</MudAlert>
|
||||
}
|
||||
</MudPaper>
|
||||
|
||||
@code {
|
||||
private DataDto? _data;
|
||||
private string? _errorMessage;
|
||||
private bool _isLoading;
|
||||
private bool _hasLoadedOnce;
|
||||
|
||||
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||
{
|
||||
if (firstRender)
|
||||
await LoadDataAsync();
|
||||
}
|
||||
|
||||
private async Task LoadDataAsync()
|
||||
{
|
||||
_isLoading = true;
|
||||
try
|
||||
{
|
||||
_data = await Http.GetFromJsonAsync<DataDto>("/api/data");
|
||||
_hasLoadedOnce = true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_errorMessage = ex.Message;
|
||||
}
|
||||
finally
|
||||
{
|
||||
_isLoading = false;
|
||||
StateHasChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Key Concepts
|
||||
|
||||
| Concept | Usage | Example |
|
||||
|---------|-------|---------|
|
||||
| Render Mode | Control where component runs | `@rendermode InteractiveWebAssembly` |
|
||||
| CascadingParameter | Receive parent state | `[CascadingParameter] MudBlazor.IDialogReference? MudDialog` |
|
||||
| OnAfterRenderAsync | Initialize after DOM ready | `if (firstRender) await LoadAsync();` |
|
||||
| StateHasChanged | Trigger re-render | Call after async state updates |
|
||||
| NavigationManager | Programmatic navigation | `Navigation.NavigateTo("/", forceLoad: true)` |
|
||||
|
||||
## Project Structure
|
||||
|
||||
| Project | Purpose | Render Mode |
|
||||
|---------|---------|-------------|
|
||||
| `Sorcha.Admin` | Server host, auth, API proxy | Server + prerender |
|
||||
| `Sorcha.Admin.Client` | WASM components | WebAssembly |
|
||||
| `Sorcha.UI.Core` | Shared components | Both |
|
||||
| `Sorcha.UI.Web` | Main UI server | Server |
|
||||
| `Sorcha.UI.Web.Client` | Main UI WASM | WebAssembly |
|
||||
|
||||
## Common Patterns
|
||||
|
||||
### MudBlazor Dialog
|
||||
|
||||
```razor
|
||||
<MudDialog DisableSidePadding="false">
|
||||
<DialogContent>
|
||||
<MudTextField @bind-Value="_value" Label="Input" />
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<MudButton OnClick="Cancel">Cancel</MudButton>
|
||||
<MudButton Color="Color.Primary" OnClick="Submit">OK</MudButton>
|
||||
</DialogActions>
|
||||
</MudDialog>
|
||||
|
||||
@code {
|
||||
[CascadingParameter] MudBlazor.IDialogReference? MudDialog { get; set; }
|
||||
private string _value = "";
|
||||
|
||||
private void Cancel() => MudDialog?.Close();
|
||||
private void Submit() => MudDialog?.Close(DialogResult.Ok(_value));
|
||||
}
|
||||
```
|
||||
|
||||
### Opening Dialog from Parent
|
||||
|
||||
```csharp
|
||||
var dialog = await DialogService.ShowAsync<LoginDialog>("Login");
|
||||
var result = await dialog.Result;
|
||||
if (result is { Canceled: false })
|
||||
{
|
||||
// Handle success
|
||||
}
|
||||
```
|
||||
|
||||
## See Also
|
||||
|
||||
- [patterns](references/patterns.md) - Component and authentication patterns
|
||||
- [workflows](references/workflows.md) - Development and deployment workflows
|
||||
|
||||
## Related Skills
|
||||
|
||||
- See the **aspire** skill for service discovery configuration
|
||||
- See the **signalr** skill for real-time notifications
|
||||
- See the **jwt** skill for authentication token handling
|
||||
- See the **yarp** skill for API Gateway configuration
|
||||
- See the **mudblazor** skill for component library details
|
||||
|
||||
## Documentation Resources
|
||||
|
||||
> Fetch latest Blazor/MudBlazor documentation with Context7.
|
||||
|
||||
**Library ID:** `/websites/mudblazor` _(MudBlazor component library documentation)_
|
||||
|
||||
**Recommended Queries:**
|
||||
- "MudBlazor dialog service usage"
|
||||
- "MudBlazor form validation"
|
||||
- "MudBlazor data grid filtering"
|
||||
@@ -1,145 +1,112 @@
|
||||
---
|
||||
name: frontend-design
|
||||
description: Create distinctive, production-grade frontend interfaces with high design quality. Use when the user asks to build web components, pages, or applications and the visual direction matters as much as the code quality.
|
||||
origin: ECC
|
||||
description: |
|
||||
Styles Blazor WASM components with CSS and responsive design patterns using MudBlazor Material Design.
|
||||
Use when: Creating new components, styling existing components, implementing responsive layouts, adding animations/transitions, or working with the MudBlazor component library.
|
||||
allowed-tools: Read, Edit, Write, Glob, Grep, Bash
|
||||
---
|
||||
|
||||
# Frontend Design
|
||||
# Frontend-design Skill
|
||||
|
||||
Use this when the task is not just "make it work" but "make it look designed."
|
||||
Sorcha uses **MudBlazor 9.5.0** for Material Design components with **CSS Isolation** as the primary styling approach. The design system follows Material Design 3 with custom extensions for blockchain/workflow visualization.
|
||||
|
||||
This skill is for product pages, dashboards, app shells, components, or visual systems that need a clear point of view instead of generic AI-looking UI.
|
||||
## Quick Start
|
||||
|
||||
## When To Use
|
||||
### Styling a New Component
|
||||
|
||||
- building a landing page, dashboard, or app surface from scratch
|
||||
- upgrading a bland interface into something intentional and memorable
|
||||
- translating a product concept into a concrete visual direction
|
||||
- implementing a frontend where typography, composition, and motion matter
|
||||
```razor
|
||||
@* MyComponent.razor *@
|
||||
<MudPaper Elevation="1" Class="pa-4 mb-3">
|
||||
<MudText Typo="Typo.h6" Class="mb-2">Component Title</MudText>
|
||||
<MudText Typo="Typo.body2" Color="Color.Secondary">
|
||||
Description text
|
||||
</MudText>
|
||||
</MudPaper>
|
||||
```
|
||||
|
||||
## Core Principle
|
||||
### Custom Component with CSS Isolation
|
||||
|
||||
Pick a direction and commit to it.
|
||||
```razor
|
||||
@* MyCard.razor *@
|
||||
<div class="custom-card @(IsSelected ? "selected" : "")">
|
||||
<div class="card-header">@Title</div>
|
||||
<div class="card-content">@ChildContent</div>
|
||||
</div>
|
||||
|
||||
Safe-average UI is usually worse than a strong, coherent aesthetic with a few bold choices.
|
||||
@code {
|
||||
[Parameter] public string Title { get; set; } = "";
|
||||
[Parameter] public RenderFragment? ChildContent { get; set; }
|
||||
[Parameter] public bool IsSelected { get; set; }
|
||||
}
|
||||
```
|
||||
|
||||
## Design Workflow
|
||||
```css
|
||||
/* MyCard.razor.css */
|
||||
.custom-card {
|
||||
background: white;
|
||||
border: 2px solid #1976d2;
|
||||
border-radius: 10px;
|
||||
box-shadow: 0 2px 8px rgba(0,0,0,0.12);
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
### 1. Frame the interface first
|
||||
.custom-card:hover {
|
||||
box-shadow: 0 4px 12px rgba(0,0,0,0.18);
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
Before coding, settle:
|
||||
.custom-card.selected {
|
||||
border-color: #0d47a1;
|
||||
border-width: 3px;
|
||||
}
|
||||
```
|
||||
|
||||
- purpose
|
||||
- audience
|
||||
- emotional tone
|
||||
- visual direction
|
||||
- one thing the user should remember
|
||||
## Key Concepts
|
||||
|
||||
Possible directions:
|
||||
| Concept | Usage | Example |
|
||||
|---------|-------|---------|
|
||||
| CSS Isolation | Component-scoped styles | `Component.razor.css` |
|
||||
| MudBlazor Utility | Spacing, flex, alignment | `Class="d-flex pa-4 mb-3"` |
|
||||
| Color System | Semantic colors | `Color.Primary`, `Color.Error` |
|
||||
| Typography | Text hierarchy | `Typo.h6`, `Typo.body2` |
|
||||
| Elevation | Shadow depth | `Elevation="1"` (0-24) |
|
||||
| Breakpoint | Responsive | `Breakpoint.Sm` (641px) |
|
||||
|
||||
- brutally minimal
|
||||
- editorial
|
||||
- industrial
|
||||
- luxury
|
||||
- playful
|
||||
- geometric
|
||||
- retro-futurist
|
||||
- soft and organic
|
||||
- maximalist
|
||||
## Common Patterns
|
||||
|
||||
Do not mix directions casually. Choose one and execute it cleanly.
|
||||
### Flex Layout with Gap
|
||||
|
||||
### 2. Build the visual system
|
||||
```razor
|
||||
<div class="d-flex align-center gap-2 mb-3">
|
||||
<MudIcon Icon="@Icons.Material.Filled.Settings" />
|
||||
<MudText Typo="Typo.body1">Settings</MudText>
|
||||
<MudSpacer />
|
||||
<MudChip T="string" Size="Size.Small" Color="Color.Info">Active</MudChip>
|
||||
</div>
|
||||
```
|
||||
|
||||
Define:
|
||||
### Panel with Header/Content Pattern
|
||||
|
||||
- type hierarchy
|
||||
- color variables
|
||||
- spacing rhythm
|
||||
- layout logic
|
||||
- motion rules
|
||||
- surface / border / shadow treatment
|
||||
```razor
|
||||
<MudPaper Elevation="1" Class="panel">
|
||||
<div class="panel-header">
|
||||
<MudText Typo="Typo.subtitle1">Panel Title</MudText>
|
||||
</div>
|
||||
<div class="panel-content">
|
||||
@* Content here *@
|
||||
</div>
|
||||
</MudPaper>
|
||||
```
|
||||
|
||||
Use CSS variables or the project's token system so the interface stays coherent as it grows.
|
||||
## See Also
|
||||
|
||||
### 3. Compose with intention
|
||||
- [aesthetics](references/aesthetics.md) - Color system, typography, brand identity
|
||||
- [components](references/components.md) - MudBlazor component patterns
|
||||
- [layouts](references/layouts.md) - Page structure, responsive grids
|
||||
- [motion](references/motion.md) - Transitions, hover effects
|
||||
- [patterns](references/patterns.md) - DO/DON'T design decisions
|
||||
|
||||
Prefer:
|
||||
## Related Skills
|
||||
|
||||
- asymmetry when it sharpens hierarchy
|
||||
- overlap when it creates depth
|
||||
- strong whitespace when it clarifies focus
|
||||
- dense layouts only when the product benefits from density
|
||||
|
||||
Avoid defaulting to a symmetrical card grid unless it is clearly the right fit.
|
||||
|
||||
### 4. Make motion meaningful
|
||||
|
||||
Use animation to:
|
||||
|
||||
- reveal hierarchy
|
||||
- stage information
|
||||
- reinforce user action
|
||||
- create one or two memorable moments
|
||||
|
||||
Do not scatter generic micro-interactions everywhere. One well-directed load sequence is usually stronger than twenty random hover effects.
|
||||
|
||||
## Strong Defaults
|
||||
|
||||
### Typography
|
||||
|
||||
- pick fonts with character
|
||||
- pair a distinctive display face with a readable body face when appropriate
|
||||
- avoid generic defaults when the page is design-led
|
||||
|
||||
### Color
|
||||
|
||||
- commit to a clear palette
|
||||
- one dominant field with selective accents usually works better than evenly weighted rainbow palettes
|
||||
- avoid cliché purple-gradient-on-white unless the product genuinely calls for it
|
||||
|
||||
### Background
|
||||
|
||||
Use atmosphere:
|
||||
|
||||
- gradients
|
||||
- meshes
|
||||
- textures
|
||||
- subtle noise
|
||||
- patterns
|
||||
- layered transparency
|
||||
|
||||
Flat empty backgrounds are rarely the best answer for a product-facing page.
|
||||
|
||||
### Layout
|
||||
|
||||
- break the grid when the composition benefits from it
|
||||
- use diagonals, offsets, and grouping intentionally
|
||||
- keep reading flow obvious even when the layout is unconventional
|
||||
|
||||
## Anti-Patterns
|
||||
|
||||
Never default to:
|
||||
|
||||
- interchangeable SaaS hero sections
|
||||
- generic card piles with no hierarchy
|
||||
- random accent colors without a system
|
||||
- placeholder-feeling typography
|
||||
- motion that exists only because animation was easy to add
|
||||
|
||||
## Execution Rules
|
||||
|
||||
- preserve the established design system when working inside an existing product
|
||||
- match technical complexity to the visual idea
|
||||
- keep accessibility and responsiveness intact
|
||||
- frontends should feel deliberate on desktop and mobile
|
||||
|
||||
## Quality Gate
|
||||
|
||||
Before delivering:
|
||||
|
||||
- the interface has a clear visual point of view
|
||||
- typography and spacing feel intentional
|
||||
- color and motion support the product instead of decorating it randomly
|
||||
- the result does not read like generic AI UI
|
||||
- the implementation is production-grade, not just visually interesting
|
||||
- See the **blazor** skill for component lifecycle and state management
|
||||
- See the **signalr** skill for real-time UI updates
|
||||
Reference in New Issue
Block a user