Claude
Skills
Sign in
Back

skills

Included with Lifetime
$97 forever

# Blazor Framework - Quick Reference (SKILL.md)

General

What this skill does

# Blazor Framework - Quick Reference (SKILL.md)

**Version**: 1.0.0
**Target**: .NET 8.0+ with Blazor Server/WebAssembly
**UI Library**: Microsoft Fluent UI Blazor Components
**Purpose**: Fast lookup for common Blazor patterns and best practices

---

## 1. Blazor Hosting Models

### Blazor Server

**Characteristics**:
- Server-side rendering with SignalR connection
- Stateful connection to server required
- Small initial download (~2MB), fast startup
- UI events sent to server via SignalR

**Setup**:
```csharp
// Program.cs
builder.Services.AddServerSideBlazor();
app.MapBlazorHub();
app.MapFallbackToPage("/_Host");
```

**Use Cases**: Internal apps, intranet, enterprise applications

---

### Blazor WebAssembly

**Characteristics**:
- Client-side execution in browser via WebAssembly
- Full .NET runtime in browser
- Larger initial download (~10MB), but offline capable
- No server connection after initial load

**Setup**:
```csharp
// Program.cs (Client)
builder.Services.AddBlazorWebAssembly();
await builder.Build().RunAsync();
```

**Use Cases**: Public-facing apps, PWAs, offline-first applications

---

### Render Modes (.NET 8+)

```razor
@* Server-side with SignalR *@
@rendermode InteractiveServer

@* Client-side WebAssembly *@
@rendermode InteractiveWebAssembly

@* Auto: Server initially, then WebAssembly after download *@
@rendermode InteractiveAuto

@* Static: Server-side rendering without interactivity *@
@rendermode @(new Microsoft.AspNetCore.Components.Web.RenderMode.Static)
```

---

## 2. Component Architecture

### Basic Component Structure

```razor
@page "/counter"
@using MyApp.Services

<h3>@Title</h3>
<p>Current count: @currentCount</p>
<button @onclick="IncrementCount">Click me</button>

@code {
    [Parameter]
    public string Title { get; set; } = "Counter";

    [Parameter]
    public EventCallback<int> OnCountChanged { get; set; }

    private int currentCount = 0;

    private async Task IncrementCount()
    {
        currentCount++;
        await OnCountChanged.InvokeAsync(currentCount);
    }
}
```

---

### Component Parameters

```csharp
// Required parameter
[Parameter, EditorRequired]
public string Name { get; set; } = "";

// Optional parameter with default
[Parameter]
public int MaxCount { get; set; } = 10;

// EventCallback (parent-child communication)
[Parameter]
public EventCallback<string> OnValueChanged { get; set; }

// Cascading parameter (from ancestor)
[CascadingParameter]
public AppState AppState { get; set; } = default!;

// Capture unmatched attributes
[Parameter(CaptureUnmatchedValues = true)]
public Dictionary<string, object>? AdditionalAttributes { get; set; }
```

---

### Component Lifecycle

```csharp
// 1. Parameters set (before initialization)
public override void SetParametersAsync(ParameterView parameters)
{
    base.SetParametersAsync(parameters);
}

// 2. Component initialization (once)
protected override void OnInitialized()
{
    // Synchronous initialization
}

protected override async Task OnInitializedAsync()
{
    // Async initialization (preferred for data loading)
    data = await DataService.GetDataAsync();
}

// 3. Parameters set (every time parameters change)
protected override void OnParametersSet()
{
    // React to parameter changes
}

protected override async Task OnParametersSetAsync()
{
    // Async parameter processing
}

// 4. After rendering
protected override void OnAfterRender(bool firstRender)
{
    if (firstRender)
    {
        // One-time setup after first render
    }
}

protected override async Task OnAfterRenderAsync(bool firstRender)
{
    if (firstRender)
    {
        // JS interop, focus management
        await JS.InvokeVoidAsync("initializeComponent");
    }
}

// 5. Determine if re-render needed
protected override bool ShouldRender()
{
    // Return false to skip re-render
    return true;
}

// 6. Disposal (cleanup)
public void Dispose()
{
    // Unsubscribe from events, dispose resources
    AppState.OnChange -= StateHasChanged;
}

public async ValueTask DisposeAsync()
{
    // Async disposal
    if (hubConnection is not null)
    {
        await hubConnection.DisposeAsync();
    }
}
```

---

## 3. Fluent UI Components

### Layout Components

```razor
@using Microsoft.FluentUI.AspNetCore.Components

@* Vertical stack with gap *@
<FluentStack Orientation="Orientation.Vertical" VerticalGap="16">
    <h1>Title</h1>
    <p>Content</p>
</FluentStack>

@* Horizontal stack *@
<FluentStack Orientation="Orientation.Horizontal" HorizontalGap="8">
    <FluentButton>Cancel</FluentButton>
    <FluentButton Appearance="Appearance.Accent">Save</FluentButton>
</FluentStack>

@* Grid layout *@
<FluentGrid Spacing="16">
    <FluentGridItem xs="12" sm="6" md="4">
        <FluentCard>Column 1</FluentCard>
    </FluentGridItem>
    <FluentGridItem xs="12" sm="6" md="4">
        <FluentCard>Column 2</FluentCard>
    </FluentGridItem>
</FluentGrid>
```

---

### Input Components

```razor
@* Text input *@
<FluentTextField
    @bind-Value="name"
    Label="Name"
    Placeholder="Enter your name"
    Required="true" />

@* Text area *@
<FluentTextArea
    @bind-Value="description"
    Label="Description"
    Rows="4" />

@* Number input *@
<FluentNumberField
    @bind-Value="age"
    Label="Age"
    Min="0"
    Max="150" />

@* Select dropdown *@
<FluentSelect
    @bind-Value="selectedOption"
    Label="Choose option"
    Items="@options"
    OptionText="@(x => x.Name)"
    OptionValue="@(x => x.Id)" />

@* Checkbox *@
<FluentCheckbox
    @bind-Value="accepted"
    Label="I accept the terms" />

@* Switch toggle *@
<FluentSwitch
    @bind-Value="isEnabled"
    Label="Enable feature" />

@* Date picker *@
<FluentDatePicker
    @bind-Value="selectedDate"
    Label="Select date" />
```

---

### Buttons

```razor
@* Primary button *@
<FluentButton Appearance="Appearance.Accent" OnClick="Submit">
    Submit
</FluentButton>

@* Secondary button *@
<FluentButton Appearance="Appearance.Neutral">
    Cancel
</FluentButton>

@* Icon button *@
<FluentIconButton
    Icon="@(new Icons.Regular.Size20.Add())"
    aria-label="Add item"
    OnClick="AddItem" />

@* Split button *@
<FluentSplitButton Text="Actions">
    <FluentMenuItem OnClick="Edit">Edit</FluentMenuItem>
    <FluentMenuItem OnClick="Delete">Delete</FluentMenuItem>
</FluentSplitButton>
```

---

### Data Display

```razor
@* Card *@
<FluentCard>
    <h3>Card Title</h3>
    <p>Card content goes here.</p>
</FluentCard>

@* Data grid with sorting *@
<FluentDataGrid Items="@users" Virtualize="true">
    <PropertyColumn Property="@(u => u.Name)" Sortable="true" />
    <PropertyColumn Property="@(u => u.Email)" />
    <PropertyColumn Property="@(u => u.CreatedAt)" Format="yyyy-MM-dd" Sortable="true" />
    <TemplateColumn Title="Actions">
        <FluentButton OnClick="@(() => EditUser(context))">Edit</FluentButton>
    </TemplateColumn>
</FluentDataGrid>

@* Accordion *@
<FluentAccordion>
    <FluentAccordionItem Heading="Section 1">
        Content for section 1
    </FluentAccordionItem>
    <FluentAccordionItem Heading="Section 2">
        Content for section 2
    </FluentAccordionItem>
</FluentAccordion>
```

---

### Feedback Components

```razor
@* Dialog *@
<FluentDialog @bind-Hidden="hideDialog" Modal="true">
    <h2>Confirmation</h2>
    <p>Are you sure you want to delete this item?</p>
    <FluentButton Appearance="Appearance.Accent" OnClick="ConfirmDelete">
        Yes, Delete
    </FluentButton>
    <FluentButton OnClick="@(() => hideDialog = true)">
        Cancel
    </FluentButton>
</FluentDialog>

@* Message bar (notification) *@
<FluentMessageBar Intent="MessageIntent.Success" Visible="@showSuccess">
    Item saved successfully!
</FluentMessageBar>

@* Progress ring (loading spinner) *@
<FluentProgressRing Visible="@isLoading" />

@* Toast notification *@
@inject IToastService ToastService

@code {
    private void ShowToast()
    {
        ToastService.ShowSuccess("Operation completed successfully!");
    }
}
```

--
Files: 34
Size: 391.7 KB
Complexity: 56/100
Category: General

Related in General