```
---
## Sidebar Layout Pattern
```razor
@* MainLayout.razor *@
My AppMain
Home
Settings
John Doe
...@Body
```
---
## Data Grid Patterns
### Basic Grid
```razor
@order.Status
```
### Server-Side Grid
```razor
@code {
private async Task> FetchPage(DataGridDataRequest req)
{
var (items, total) = await _api.GetProductsAsync(
page: req.StartRow / req.PageSize,
pageSize: req.PageSize,
sortField: req.SortModel.FirstOrDefault()?.ColId,
sortDir: req.SortModel.FirstOrDefault()?.Sort,
filter: req.FilterModel.GetValueOrDefault("Name")?.Filter);
return new DataGridDataResponse { Items = items, TotalCount = total };
}
}
```
---
## Render Mode Gotchas
### Interactive Components Need Interactive Render Mode
Tabs, NavigationMenu, Combobox, DataGrid -- all require interactive rendering.
```razor
@* App.razor -- set global interactive render mode *@
```
```razor
@* Or per-component in a Static SSR page *@
...
```
### InteractiveAuto Requires Registration in Both Projects
```csharp
// Server project Program.cs
builder.Services.AddRazorComponents()
.AddInteractiveServerComponents()
.AddInteractiveWebAssemblyComponents();
// Both Server AND WASM Client Program.cs
builder.Services.AddNeoUIPrimitives();
builder.Services.AddNeoUIComponents();
builder.Services.AddScoped();
```
### SidebarProvider with Static Rendering
```razor
@* Set StaticRendering="true" when parent renders statically *@
...
```
---
## Keyboard Shortcuts
```razor
@inject IKeyboardShortcutService KeyboardShortcuts
@code {
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
await KeyboardShortcuts.RegisterAsync("Ctrl+K", OpenCommandPalette);
await KeyboardShortcuts.RegisterAsync("Escape", CloseAll);
}
}
private void OpenCommandPalette() { /* ... */ }
private void CloseAll() { /* ... */ }
}
```
---
## Loading States Pattern
```razor
@if (_loading)
{
}
else if (_error is not null)
{
Failed to load@_error
}
else if (!_items.Any())
{
No items yetCreate your first item to get started.
}
else
{
@foreach (var item in _items)
{
}
}
```