mirror of
https://github.com/github/awesome-copilot.git
synced 2026-02-20 02:15:12 +00:00
Add fluentui-blazor skill
Add a new skill for using the Microsoft Fluent UI Blazor component library (Microsoft.FluentUI.AspNetCore.Components v4) in Blazor applications. Includes guidance on setup, component usage, theming, data grids, layout and navigation.
This commit is contained in:
@@ -35,6 +35,7 @@ Skills differ from other primitives by supporting bundled assets (scripts, code
|
||||
| [copilot-sdk](../skills/copilot-sdk/SKILL.md) | Build agentic applications with GitHub Copilot SDK. Use when embedding AI agents in apps, creating custom tools, implementing streaming responses, managing sessions, connecting to MCP servers, or creating custom agents. Triggers on Copilot SDK, GitHub SDK, agentic app, embed Copilot, programmable agent, MCP server, custom agent. | None |
|
||||
| [create-web-form](../skills/create-web-form/SKILL.md) | Create robust, accessible web forms with best practices for HTML structure, CSS styling, JavaScript interactivity, form validation, and server-side processing. Use when asked to "create a form", "build a web form", "add a contact form", "make a signup form", or when building any HTML form with data handling. Covers PHP and Python backends, MySQL database integration, REST APIs, XML data exchange, accessibility (ARIA), and progressive web apps. | `references/accessibility.md`<br />`references/aria-form-role.md`<br />`references/css-styling.md`<br />`references/form-basics.md`<br />`references/form-controls.md`<br />`references/form-data-handling.md`<br />`references/html-form-elements.md`<br />`references/html-form-example.md`<br />`references/hypertext-transfer-protocol.md`<br />`references/javascript.md`<br />`references/php-cookies.md`<br />`references/php-forms.md`<br />`references/php-json.md`<br />`references/php-mysql-database.md`<br />`references/progressive-web-app.md`<br />`references/python-as-web-framework.md`<br />`references/python-contact-form.md`<br />`references/python-flask-app.md`<br />`references/python-flask.md`<br />`references/security.md`<br />`references/styling-web-forms.md`<br />`references/web-api.md`<br />`references/web-performance.md`<br />`references/xml.md` |
|
||||
| [excalidraw-diagram-generator](../skills/excalidraw-diagram-generator/SKILL.md) | Generate Excalidraw diagrams from natural language descriptions. Use when asked to "create a diagram", "make a flowchart", "visualize a process", "draw a system architecture", "create a mind map", or "generate an Excalidraw file". Supports flowcharts, relationship diagrams, mind maps, and system architecture diagrams. Outputs .excalidraw JSON files that can be opened directly in Excalidraw. | `references/element-types.md`<br />`references/excalidraw-schema.md`<br />`scripts/.gitignore`<br />`scripts/README.md`<br />`scripts/add-arrow.py`<br />`scripts/add-icon-to-diagram.py`<br />`scripts/split-excalidraw-library.py`<br />`templates/business-flow-swimlane-template.excalidraw`<br />`templates/class-diagram-template.excalidraw`<br />`templates/data-flow-diagram-template.excalidraw`<br />`templates/er-diagram-template.excalidraw`<br />`templates/flowchart-template.excalidraw`<br />`templates/mindmap-template.excalidraw`<br />`templates/relationship-template.excalidraw`<br />`templates/sequence-diagram-template.excalidraw` |
|
||||
| [fluentui-blazor](../skills/fluentui-blazor/SKILL.md) | Guide for using the Microsoft Fluent UI Blazor component library (Microsoft.FluentUI.AspNetCore.Components NuGet package) in Blazor applications. Use this when the user is building a Blazor app with Fluent UI components, setting up the library, using FluentUI components like FluentButton, FluentDataGrid, FluentDialog, FluentToast, FluentNavMenu, FluentTextField, FluentSelect, FluentAutocomplete, FluentDesignTheme, or any component prefixed with "Fluent". Also use when troubleshooting missing providers, JS interop issues, or theming. | `references/DATAGRID.md`<br />`references/LAYOUT-AND-NAVIGATION.md`<br />`references/SETUP.md`<br />`references/THEMING.md` |
|
||||
| [gh-cli](../skills/gh-cli/SKILL.md) | GitHub CLI (gh) comprehensive reference for repositories, issues, pull requests, Actions, projects, releases, gists, codespaces, organizations, extensions, and all GitHub operations from the command line. | None |
|
||||
| [git-commit](../skills/git-commit/SKILL.md) | Execute git commit with conventional commit message analysis, intelligent staging, and message generation. Use when user asks to commit changes, create a git commit, or mentions "/commit". Supports: (1) Auto-detecting type and scope from changes, (2) Generating conventional commit messages from diff, (3) Interactive commit with optional type/scope/description overrides, (4) Intelligent file staging for logical grouping | None |
|
||||
| [github-issues](../skills/github-issues/SKILL.md) | Create, update, and manage GitHub issues using MCP tools. Use this skill when users want to create bug reports, feature requests, or task issues, update existing issues, add labels/assignees/milestones, or manage issue workflows. Triggers on requests like "create an issue", "file a bug", "request a feature", "update issue X", or any GitHub issue management task. | `references/templates.md` |
|
||||
|
||||
231
skills/fluentui-blazor/SKILL.md
Normal file
231
skills/fluentui-blazor/SKILL.md
Normal file
@@ -0,0 +1,231 @@
|
||||
---
|
||||
name: fluentui-blazor
|
||||
description: >
|
||||
Guide for using the Microsoft Fluent UI Blazor component library
|
||||
(Microsoft.FluentUI.AspNetCore.Components NuGet package) in Blazor applications.
|
||||
Use this when the user is building a Blazor app with Fluent UI components,
|
||||
setting up the library, using FluentUI components like FluentButton, FluentDataGrid,
|
||||
FluentDialog, FluentToast, FluentNavMenu, FluentTextField, FluentSelect,
|
||||
FluentAutocomplete, FluentDesignTheme, or any component prefixed with "Fluent".
|
||||
Also use when troubleshooting missing providers, JS interop issues, or theming.
|
||||
---
|
||||
|
||||
# Fluent UI Blazor — Consumer Usage Guide
|
||||
|
||||
This skill teaches how to correctly use the **Microsoft.FluentUI.AspNetCore.Components** (version 4) NuGet package in Blazor applications.
|
||||
|
||||
## Critical Rules
|
||||
|
||||
### 1. No manual `<script>` or `<link>` tags needed
|
||||
|
||||
The library auto-loads all CSS and JS via Blazor's static web assets and JS initializers. **Never tell users to add `<script>` or `<link>` tags for the core library.**
|
||||
|
||||
### 2. Providers are mandatory for service-based components
|
||||
|
||||
These provider components **MUST** be added to the root layout (e.g. `MainLayout.razor`) for their corresponding services to work. Without them, service calls **fail silently** (no error, no UI).
|
||||
|
||||
```razor
|
||||
<FluentToastProvider />
|
||||
<FluentDialogProvider />
|
||||
<FluentMessageBarProvider />
|
||||
<FluentTooltipProvider />
|
||||
<FluentKeyCodeProvider />
|
||||
```
|
||||
|
||||
### 3. Service registration in Program.cs
|
||||
|
||||
```csharp
|
||||
builder.Services.AddFluentUIComponents();
|
||||
|
||||
// Or with configuration:
|
||||
builder.Services.AddFluentUIComponents(options =>
|
||||
{
|
||||
options.UseTooltipServiceProvider = true; // default: true
|
||||
options.ServiceLifetime = ServiceLifetime.Scoped; // default
|
||||
});
|
||||
```
|
||||
|
||||
**ServiceLifetime rules:**
|
||||
- `ServiceLifetime.Scoped` — for Blazor Server / Interactive (default)
|
||||
- `ServiceLifetime.Singleton` — for Blazor WebAssembly standalone
|
||||
- `ServiceLifetime.Transient` — **throws `NotSupportedException`**
|
||||
|
||||
### 4. Icons require a separate NuGet package
|
||||
|
||||
```
|
||||
dotnet add package Microsoft.FluentUI.AspNetCore.Components.Icons
|
||||
```
|
||||
|
||||
Usage with a `@using` alias:
|
||||
|
||||
```razor
|
||||
@using Icons = Microsoft.FluentUI.AspNetCore.Components.Icons
|
||||
|
||||
<FluentIcon Value="@(Icons.Regular.Size24.Save)" />
|
||||
<FluentIcon Value="@(Icons.Filled.Size20.Delete)" Color="@Color.Error" />
|
||||
```
|
||||
|
||||
Pattern: `Icons.[Variant].[Size].[Name]`
|
||||
- Variants: `Regular`, `Filled`
|
||||
- Sizes: `Size12`, `Size16`, `Size20`, `Size24`, `Size28`, `Size32`, `Size48`
|
||||
|
||||
Custom image: `Icon.FromImageUrl("/path/to/image.png")`
|
||||
|
||||
**Never use string-based icon names** — icons are strongly-typed classes.
|
||||
|
||||
### 5. List component binding model
|
||||
|
||||
`FluentSelect<TOption>`, `FluentCombobox<TOption>`, `FluentListbox<TOption>`, and `FluentAutocomplete<TOption>` do NOT work like `<InputSelect>`. They use:
|
||||
|
||||
- `Items` — the data source (`IEnumerable<TOption>`)
|
||||
- `OptionText` — `Func<TOption, string?>` to extract display text
|
||||
- `OptionValue` — `Func<TOption, string?>` to extract the value string
|
||||
- `SelectedOption` / `SelectedOptionChanged` — for single selection binding
|
||||
- `SelectedOptions` / `SelectedOptionsChanged` — for multi-selection binding
|
||||
|
||||
```razor
|
||||
<FluentSelect Items="@countries"
|
||||
OptionText="@(c => c.Name)"
|
||||
OptionValue="@(c => c.Code)"
|
||||
@bind-SelectedOption="@selectedCountry"
|
||||
Label="Country" />
|
||||
```
|
||||
|
||||
**NOT** like this (wrong pattern):
|
||||
```razor
|
||||
@* WRONG — do not use InputSelect pattern *@
|
||||
<FluentSelect @bind-Value="@selectedValue">
|
||||
<option value="1">One</option>
|
||||
</FluentSelect>
|
||||
```
|
||||
|
||||
### 6. FluentAutocomplete specifics
|
||||
|
||||
- Use `ValueText` (NOT `Value` — it's obsolete) for the search input text
|
||||
- `OnOptionsSearch` is the required callback to filter options
|
||||
- Default is `Multiple="true"`
|
||||
|
||||
```razor
|
||||
<FluentAutocomplete TOption="Person"
|
||||
OnOptionsSearch="@OnSearch"
|
||||
OptionText="@(p => p.FullName)"
|
||||
@bind-SelectedOptions="@selectedPeople"
|
||||
Label="Search people" />
|
||||
|
||||
@code {
|
||||
private void OnSearch(OptionsSearchEventArgs<Person> args)
|
||||
{
|
||||
args.Items = allPeople.Where(p =>
|
||||
p.FullName.Contains(args.Text, StringComparison.OrdinalIgnoreCase));
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 7. Dialog service pattern
|
||||
|
||||
**Do NOT toggle visibility of `<FluentDialog>` tags.** The service pattern is:
|
||||
|
||||
1. Create a content component implementing `IDialogContentComponent<TData>`:
|
||||
|
||||
```csharp
|
||||
public partial class EditPersonDialog : IDialogContentComponent<Person>
|
||||
{
|
||||
[Parameter] public Person Content { get; set; } = default!;
|
||||
|
||||
[CascadingParameter] public FluentDialog Dialog { get; set; } = default!;
|
||||
|
||||
private async Task SaveAsync()
|
||||
{
|
||||
await Dialog.CloseAsync(Content);
|
||||
}
|
||||
|
||||
private async Task CancelAsync()
|
||||
{
|
||||
await Dialog.CancelAsync();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
2. Show the dialog via `IDialogService`:
|
||||
|
||||
```csharp
|
||||
[Inject] private IDialogService DialogService { get; set; } = default!;
|
||||
|
||||
private async Task ShowEditDialog()
|
||||
{
|
||||
var dialog = await DialogService.ShowDialogAsync<EditPersonDialog, Person>(
|
||||
person,
|
||||
new DialogParameters
|
||||
{
|
||||
Title = "Edit Person",
|
||||
PrimaryAction = "Save",
|
||||
SecondaryAction = "Cancel",
|
||||
Width = "500px",
|
||||
PreventDismissOnOverlayClick = true,
|
||||
});
|
||||
|
||||
var result = await dialog.Result;
|
||||
if (!result.Cancelled)
|
||||
{
|
||||
var updatedPerson = result.Data as Person;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
For convenience dialogs:
|
||||
```csharp
|
||||
await DialogService.ShowConfirmationAsync("Are you sure?", "Yes", "No");
|
||||
await DialogService.ShowSuccessAsync("Done!");
|
||||
await DialogService.ShowErrorAsync("Something went wrong.");
|
||||
```
|
||||
|
||||
### 8. Toast notifications
|
||||
|
||||
```csharp
|
||||
[Inject] private IToastService ToastService { get; set; } = default!;
|
||||
|
||||
ToastService.ShowSuccess("Item saved successfully");
|
||||
ToastService.ShowError("Failed to save");
|
||||
ToastService.ShowWarning("Check your input");
|
||||
ToastService.ShowInfo("New update available");
|
||||
```
|
||||
|
||||
`FluentToastProvider` parameters: `Position` (default `TopRight`), `Timeout` (default 7000ms), `MaxToastCount` (default 4).
|
||||
|
||||
### 9. Design tokens and themes work only after render
|
||||
|
||||
Design tokens rely on JS interop. **Never set them in `OnInitialized`** — use `OnAfterRenderAsync`.
|
||||
|
||||
```razor
|
||||
<FluentDesignTheme Mode="DesignThemeModes.System"
|
||||
OfficeColor="OfficeColor.Teams"
|
||||
StorageName="mytheme" />
|
||||
```
|
||||
|
||||
### 10. FluentEditForm vs EditForm
|
||||
|
||||
`FluentEditForm` is only needed inside `FluentWizard` steps (per-step validation). For regular forms, use standard `EditForm` with Fluent form components:
|
||||
|
||||
```razor
|
||||
<EditForm Model="@model" OnValidSubmit="HandleSubmit">
|
||||
<DataAnnotationsValidator />
|
||||
<FluentTextField @bind-Value="@model.Name" Label="Name" Required />
|
||||
<FluentSelect Items="@options"
|
||||
OptionText="@(o => o.Label)"
|
||||
@bind-SelectedOption="@model.Category"
|
||||
Label="Category" />
|
||||
<FluentValidationSummary />
|
||||
<FluentButton Type="ButtonType.Submit" Appearance="Appearance.Accent">Save</FluentButton>
|
||||
</EditForm>
|
||||
```
|
||||
|
||||
Use `FluentValidationMessage` and `FluentValidationSummary` instead of standard Blazor validation components for Fluent styling.
|
||||
|
||||
## Reference files
|
||||
|
||||
For detailed guidance on specific topics, see:
|
||||
|
||||
- [Setup and configuration](references/SETUP.md)
|
||||
- [Layout and navigation](references/LAYOUT-AND-NAVIGATION.md)
|
||||
- [Data grid](references/DATAGRID.md)
|
||||
- [Theming](references/THEMING.md)
|
||||
162
skills/fluentui-blazor/references/DATAGRID.md
Normal file
162
skills/fluentui-blazor/references/DATAGRID.md
Normal file
@@ -0,0 +1,162 @@
|
||||
# FluentDataGrid
|
||||
|
||||
`FluentDataGrid<TGridItem>` is a strongly-typed generic component for displaying tabular data.
|
||||
|
||||
## Basic Usage
|
||||
|
||||
```razor
|
||||
<FluentDataGrid Items="@people" TGridItem="Person">
|
||||
<PropertyColumn Property="@(p => p.Name)" Sortable="true" />
|
||||
<PropertyColumn Property="@(p => p.Email)" />
|
||||
<PropertyColumn Property="@(p => p.BirthDate)" Format="yyyy-MM-dd" />
|
||||
<TemplateColumn Title="Actions">
|
||||
<FluentButton OnClick="@(() => Edit(context))">Edit</FluentButton>
|
||||
</TemplateColumn>
|
||||
</FluentDataGrid>
|
||||
```
|
||||
|
||||
**Critical**: Columns are child components, NOT properties. Use `PropertyColumn`, `TemplateColumn`, and `SelectColumn` within the grid.
|
||||
|
||||
## Column Types
|
||||
|
||||
### PropertyColumn
|
||||
|
||||
Binds to a property expression. Auto-derives title from property name or `[Display]` attribute.
|
||||
|
||||
```razor
|
||||
<PropertyColumn Property="@(p => p.Name)" Sortable="true" />
|
||||
<PropertyColumn Property="@(p => p.Price)" Format="C2" Title="Unit Price" />
|
||||
<PropertyColumn Property="@(p => p.Category)" Comparer="@StringComparer.OrdinalIgnoreCase" />
|
||||
```
|
||||
|
||||
Parameters: `Property` (required), `Format`, `Title`, `Sortable`, `SortBy`, `Comparer`, `IsDefaultSortColumn`, `InitialSortDirection`, `Class`, `Tooltip`.
|
||||
|
||||
### TemplateColumn
|
||||
|
||||
Full custom rendering via render fragment. `context` is the `TGridItem`.
|
||||
|
||||
```razor
|
||||
<TemplateColumn Title="Status" SortBy="@statusSort">
|
||||
<FluentBadge Appearance="Appearance.Accent"
|
||||
BackgroundColor="@(context.IsActive ? "green" : "red")">
|
||||
@(context.IsActive ? "Active" : "Inactive")
|
||||
</FluentBadge>
|
||||
</TemplateColumn>
|
||||
```
|
||||
|
||||
### SelectColumn
|
||||
|
||||
Checkbox selection column.
|
||||
|
||||
```razor
|
||||
<SelectColumn TGridItem="Person"
|
||||
SelectMode="DataGridSelectMode.Multiple"
|
||||
@bind-SelectedItems="@selectedPeople" />
|
||||
```
|
||||
|
||||
Modes: `DataGridSelectMode.Single`, `DataGridSelectMode.Multiple`.
|
||||
|
||||
## Data Sources
|
||||
|
||||
Two mutually exclusive approaches:
|
||||
|
||||
### In-memory (IQueryable)
|
||||
|
||||
```razor
|
||||
<FluentDataGrid Items="@people.AsQueryable()" TGridItem="Person">
|
||||
...
|
||||
</FluentDataGrid>
|
||||
```
|
||||
|
||||
### Server-side / Custom (ItemsProvider)
|
||||
|
||||
```razor
|
||||
<FluentDataGrid ItemsProvider="@peopleProvider" TGridItem="Person">
|
||||
...
|
||||
</FluentDataGrid>
|
||||
|
||||
@code {
|
||||
private GridItemsProvider<Person> peopleProvider = async request =>
|
||||
{
|
||||
var result = await PeopleService.GetPeopleAsync(
|
||||
request.StartIndex,
|
||||
request.Count ?? 50,
|
||||
request.GetSortByProperties().FirstOrDefault());
|
||||
|
||||
return GridItemsProviderResult.From(result.Items, result.TotalCount);
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
### EF Core Adapter
|
||||
|
||||
```csharp
|
||||
// Program.cs
|
||||
builder.Services.AddDataGridEntityFrameworkAdapter();
|
||||
```
|
||||
|
||||
```razor
|
||||
<FluentDataGrid Items="@dbContext.People" TGridItem="Person">
|
||||
...
|
||||
</FluentDataGrid>
|
||||
```
|
||||
|
||||
## Pagination
|
||||
|
||||
```razor
|
||||
<FluentDataGrid Items="@people" Pagination="@pagination" TGridItem="Person">
|
||||
...
|
||||
</FluentDataGrid>
|
||||
|
||||
<FluentPaginator State="@pagination" />
|
||||
|
||||
@code {
|
||||
private PaginationState pagination = new() { ItemsPerPage = 10 };
|
||||
}
|
||||
```
|
||||
|
||||
## Virtualization
|
||||
|
||||
For large datasets, enable virtualization:
|
||||
|
||||
```razor
|
||||
<FluentDataGrid Items="@people" Virtualize="true" ItemSize="46" TGridItem="Person">
|
||||
...
|
||||
</FluentDataGrid>
|
||||
```
|
||||
|
||||
`ItemSize` is the estimated row height in pixels (default varies). Important for scroll position calculations.
|
||||
|
||||
## Key Parameters
|
||||
|
||||
| Parameter | Type | Description |
|
||||
|---|---|---|
|
||||
| `Items` | `IQueryable<TGridItem>?` | In-memory data source |
|
||||
| `ItemsProvider` | `GridItemsProvider<TGridItem>?` | Async data provider |
|
||||
| `Pagination` | `PaginationState?` | Pagination state |
|
||||
| `Virtualize` | `bool` | Enable virtualization |
|
||||
| `ItemSize` | `float` | Estimated row height (px) |
|
||||
| `ItemKey` | `Func<TGridItem, object>?` | Stable key for `@key` |
|
||||
| `ResizableColumns` | `bool` | Enable column resize |
|
||||
| `HeaderCellAsButtonWithMenu` | `bool` | Sortable header UI |
|
||||
| `GridTemplateColumns` | `string?` | CSS grid-template-columns |
|
||||
| `Loading` | `bool` | Show loading indicator |
|
||||
| `ShowHover` | `bool` | Highlight rows on hover |
|
||||
| `OnRowClick` | `EventCallback<FluentDataGridRow<TGridItem>>` | Row click handler |
|
||||
| `OnRowDoubleClick` | `EventCallback<FluentDataGridRow<TGridItem>>` | Row double-click handler |
|
||||
| `OnRowFocus` | `EventCallback<FluentDataGridRow<TGridItem>>` | Row focus handler |
|
||||
|
||||
## Sorting
|
||||
|
||||
```razor
|
||||
<PropertyColumn Property="@(p => p.Name)" Sortable="true" IsDefaultSortColumn="true"
|
||||
InitialSortDirection="SortDirection.Ascending" />
|
||||
```
|
||||
|
||||
Or with a custom sort:
|
||||
|
||||
```razor
|
||||
<TemplateColumn Title="Full Name" SortBy="@(GridSort<Person>.ByAscending(p => p.LastName).ThenAscending(p => p.FirstName))">
|
||||
@context.LastName, @context.FirstName
|
||||
</TemplateColumn>
|
||||
```
|
||||
173
skills/fluentui-blazor/references/LAYOUT-AND-NAVIGATION.md
Normal file
173
skills/fluentui-blazor/references/LAYOUT-AND-NAVIGATION.md
Normal file
@@ -0,0 +1,173 @@
|
||||
# Layout and Navigation
|
||||
|
||||
## Layout Components
|
||||
|
||||
### FluentLayout
|
||||
|
||||
Root layout container. Use as the outermost structural component.
|
||||
|
||||
```razor
|
||||
<FluentLayout Orientation="Orientation.Vertical">
|
||||
<FluentHeader>...</FluentHeader>
|
||||
<FluentBodyContent>...</FluentBodyContent>
|
||||
<FluentFooter>...</FluentFooter>
|
||||
</FluentLayout>
|
||||
```
|
||||
|
||||
### FluentHeader / FluentFooter
|
||||
|
||||
Sticky header and footer sections within `FluentLayout`.
|
||||
|
||||
```razor
|
||||
<FluentHeader Height="50">
|
||||
<FluentStack Orientation="Orientation.Horizontal" HorizontalAlignment="HorizontalAlignment.SpaceBetween">
|
||||
<span>App Title</span>
|
||||
<FluentButton>Settings</FluentButton>
|
||||
</FluentStack>
|
||||
</FluentHeader>
|
||||
```
|
||||
|
||||
### FluentBodyContent
|
||||
|
||||
Main scrollable content area within `FluentLayout`.
|
||||
|
||||
### FluentStack
|
||||
|
||||
Flexbox container for horizontal or vertical layouts.
|
||||
|
||||
```razor
|
||||
<FluentStack Orientation="Orientation.Horizontal"
|
||||
HorizontalGap="10"
|
||||
VerticalGap="10"
|
||||
HorizontalAlignment="HorizontalAlignment.Center"
|
||||
VerticalAlignment="VerticalAlignment.Center"
|
||||
Wrap="true"
|
||||
Width="100%">
|
||||
<FluentButton>One</FluentButton>
|
||||
<FluentButton>Two</FluentButton>
|
||||
</FluentStack>
|
||||
```
|
||||
|
||||
Parameters: `Orientation`, `HorizontalGap`, `VerticalGap`, `HorizontalAlignment`, `VerticalAlignment`, `Wrap`, `Width`.
|
||||
|
||||
### FluentGrid / FluentGridItem
|
||||
|
||||
12-column responsive grid system.
|
||||
|
||||
```razor
|
||||
<FluentGrid Spacing="3" Justify="JustifyContent.Center" AdaptiveRendering="true">
|
||||
<FluentGridItem xs="12" sm="6" md="4" lg="3">
|
||||
Card 1
|
||||
</FluentGridItem>
|
||||
<FluentGridItem xs="12" sm="6" md="4" lg="3">
|
||||
Card 2
|
||||
</FluentGridItem>
|
||||
</FluentGrid>
|
||||
```
|
||||
|
||||
Size parameters (`xs`, `sm`, `md`, `lg`, `xl`, `xxl`) represent column spans out of 12. Use `AdaptiveRendering="true"` to hide items that don't fit.
|
||||
|
||||
### FluentMainLayout (convenience)
|
||||
|
||||
Pre-composed layout with header, nav menu, and body area.
|
||||
|
||||
```razor
|
||||
<FluentMainLayout Header="@header"
|
||||
SubHeader="@subheader"
|
||||
NavMenuContent="@navMenu"
|
||||
Body="@body"
|
||||
HeaderHeight="50"
|
||||
NavMenuWidth="250"
|
||||
NavMenuTitle="Navigation" />
|
||||
```
|
||||
|
||||
## Navigation Components
|
||||
|
||||
### FluentNavMenu
|
||||
|
||||
Collapsible navigation menu with keyboard support.
|
||||
|
||||
```razor
|
||||
<FluentNavMenu Width="250"
|
||||
Collapsible="true"
|
||||
@bind-Expanded="@menuExpanded"
|
||||
Title="Main navigation"
|
||||
CollapsedChildNavigation="true"
|
||||
Margin="4px 0">
|
||||
<FluentNavLink Href="/" Icon="@(Icons.Regular.Size20.Home)" Match="NavLinkMatch.All">
|
||||
Home
|
||||
</FluentNavLink>
|
||||
<FluentNavLink Href="/counter" Icon="@(Icons.Regular.Size20.NumberSymbol)">
|
||||
Counter
|
||||
</FluentNavLink>
|
||||
<FluentNavGroup Title="Admin" Icon="@(Icons.Regular.Size20.Shield)" @bind-Expanded="@adminExpanded">
|
||||
<FluentNavLink Href="/admin/users">Users</FluentNavLink>
|
||||
<FluentNavLink Href="/admin/roles">Roles</FluentNavLink>
|
||||
</FluentNavGroup>
|
||||
</FluentNavMenu>
|
||||
```
|
||||
|
||||
Key parameters:
|
||||
- `Width` — width in pixels (40px when collapsed)
|
||||
- `Collapsible` — enables expand/collapse toggle
|
||||
- `Expanded` / `ExpandedChanged` — bindable collapse state
|
||||
- `CollapsedChildNavigation` — shows flyout menus for groups when collapsed
|
||||
- `CustomToggle` — for mobile hamburger button patterns
|
||||
- `Title` — aria-label for accessibility
|
||||
|
||||
### FluentNavGroup
|
||||
|
||||
Expandable group within a nav menu.
|
||||
|
||||
```razor
|
||||
<FluentNavGroup Title="Settings"
|
||||
Icon="@(Icons.Regular.Size20.Settings)"
|
||||
@bind-Expanded="@settingsExpanded"
|
||||
Gap="2">
|
||||
<FluentNavLink Href="/settings/general">General</FluentNavLink>
|
||||
<FluentNavLink Href="/settings/profile">Profile</FluentNavLink>
|
||||
</FluentNavGroup>
|
||||
```
|
||||
|
||||
Parameters: `Title`, `Expanded`/`ExpandedChanged`, `Icon`, `IconColor`, `HideExpander`, `Gap`, `MaxHeight`, `TitleTemplate`.
|
||||
|
||||
### FluentNavLink
|
||||
|
||||
Navigation link with active state tracking.
|
||||
|
||||
```razor
|
||||
<FluentNavLink Href="/page"
|
||||
Icon="@(Icons.Regular.Size20.Document)"
|
||||
Match="NavLinkMatch.Prefix"
|
||||
Target="_blank"
|
||||
Disabled="false">
|
||||
Page Title
|
||||
</FluentNavLink>
|
||||
```
|
||||
|
||||
Parameters: `Href`, `Target`, `Match` (`NavLinkMatch.Prefix` default, or `All`), `ActiveClass`, `Icon`, `IconColor`, `Disabled`, `Tooltip`.
|
||||
|
||||
All nav components inherit from `FluentNavBase` which provides: `Icon`, `IconColor`, `CustomColor`, `Disabled`, `Tooltip`.
|
||||
|
||||
### FluentBreadcrumb / FluentBreadcrumbItem
|
||||
|
||||
```razor
|
||||
<FluentBreadcrumb>
|
||||
<FluentBreadcrumbItem Href="/">Home</FluentBreadcrumbItem>
|
||||
<FluentBreadcrumbItem Href="/products">Products</FluentBreadcrumbItem>
|
||||
<FluentBreadcrumbItem>Current Page</FluentBreadcrumbItem>
|
||||
</FluentBreadcrumb>
|
||||
```
|
||||
|
||||
### FluentTab / FluentTabs
|
||||
|
||||
```razor
|
||||
<FluentTabs @bind-ActiveTabId="@activeTab">
|
||||
<FluentTab Id="tab1" Label="Details">
|
||||
Details content
|
||||
</FluentTab>
|
||||
<FluentTab Id="tab2" Label="History">
|
||||
History content
|
||||
</FluentTab>
|
||||
</FluentTabs>
|
||||
```
|
||||
129
skills/fluentui-blazor/references/SETUP.md
Normal file
129
skills/fluentui-blazor/references/SETUP.md
Normal file
@@ -0,0 +1,129 @@
|
||||
# Setup and Configuration
|
||||
|
||||
## NuGet Packages
|
||||
|
||||
| Package | Purpose |
|
||||
|---|---|
|
||||
| `Microsoft.FluentUI.AspNetCore.Components` | Core component library (required) |
|
||||
| `Microsoft.FluentUI.AspNetCore.Components.Icons` | Icon package (optional, recommended) |
|
||||
| `Microsoft.FluentUI.AspNetCore.Components.Emojis` | Emoji package (optional) |
|
||||
| `Microsoft.FluentUI.AspNetCore.Components.DataGrid.EntityFrameworkAdapter` | EF Core adapter for DataGrid (optional) |
|
||||
| `Microsoft.FluentUI.AspNetCore.Components.DataGrid.ODataAdapter` | OData adapter for DataGrid (optional) |
|
||||
|
||||
## Program.cs Registration
|
||||
|
||||
```csharp
|
||||
builder.Services.AddFluentUIComponents();
|
||||
```
|
||||
|
||||
### Configuration Options (LibraryConfiguration)
|
||||
|
||||
| Property | Type | Default | Notes |
|
||||
|---|---|---|---|
|
||||
| `UseTooltipServiceProvider` | `bool` | `true` | Registers `ITooltipService`. If true, you MUST add `<FluentTooltipProvider>` to layout |
|
||||
| `RequiredLabel` | `MarkupString` | Red `*` | Custom markup for required field indicators |
|
||||
| `HideTooltipOnCursorLeave` | `bool` | `false` | Close tooltip when cursor leaves both anchor and tooltip |
|
||||
| `ServiceLifetime` | `ServiceLifetime` | `Scoped` | Only `Scoped` or `Singleton`. `Transient` throws! |
|
||||
| `ValidateClassNames` | `bool` | `true` | Validates CSS class names against `^-?[_a-zA-Z]+[_a-zA-Z0-9-]*$` |
|
||||
| `CollocatedJavaScriptQueryString` | `Func<string, string>?` | `v={version}` | Cache-busting for JS files |
|
||||
|
||||
### ServiceLifetime by hosting model
|
||||
|
||||
| Hosting model | ServiceLifetime |
|
||||
|---|---|
|
||||
| Blazor Server | `Scoped` (default) |
|
||||
| Blazor WebAssembly Standalone | `Singleton` |
|
||||
| Blazor Web App (Interactive) | `Scoped` (default) |
|
||||
| Blazor Hybrid (MAUI) | `Singleton` |
|
||||
|
||||
## MainLayout.razor Template
|
||||
|
||||
```razor
|
||||
@inherits LayoutComponentBase
|
||||
|
||||
<FluentLayout>
|
||||
<FluentHeader Height="50">
|
||||
My App
|
||||
</FluentHeader>
|
||||
|
||||
<FluentStack Orientation="Orientation.Horizontal" HorizontalGap="0" Style="height: 100%;">
|
||||
<FluentNavMenu Width="250" Collapsible="true" Title="Navigation">
|
||||
<FluentNavLink Href="/" Icon="@(Icons.Regular.Size20.Home)" Match="NavLinkMatch.All">Home</FluentNavLink>
|
||||
<FluentNavLink Href="/counter" Icon="@(Icons.Regular.Size20.NumberSymbol)">Counter</FluentNavLink>
|
||||
<FluentNavGroup Title="Settings" Icon="@(Icons.Regular.Size20.Settings)">
|
||||
<FluentNavLink Href="/settings/general">General</FluentNavLink>
|
||||
<FluentNavLink Href="/settings/profile">Profile</FluentNavLink>
|
||||
</FluentNavGroup>
|
||||
</FluentNavMenu>
|
||||
|
||||
<FluentBodyContent>
|
||||
<FluentStack Orientation="Orientation.Vertical" Style="padding: 1rem;">
|
||||
@Body
|
||||
</FluentStack>
|
||||
</FluentBodyContent>
|
||||
</FluentStack>
|
||||
</FluentLayout>
|
||||
|
||||
@* Required providers — place after FluentLayout *@
|
||||
<FluentToastProvider />
|
||||
<FluentDialogProvider />
|
||||
<FluentMessageBarProvider />
|
||||
<FluentTooltipProvider />
|
||||
<FluentKeyCodeProvider />
|
||||
|
||||
@* Theme — place at root *@
|
||||
<FluentDesignTheme Mode="DesignThemeModes.System"
|
||||
OfficeColor="OfficeColor.Teams"
|
||||
StorageName="mytheme" />
|
||||
```
|
||||
|
||||
Or use the convenience component:
|
||||
|
||||
```razor
|
||||
<FluentMainLayout Header="@header"
|
||||
NavMenuContent="@navMenu"
|
||||
Body="@body"
|
||||
HeaderHeight="50"
|
||||
NavMenuWidth="250"
|
||||
NavMenuTitle="Navigation" />
|
||||
|
||||
@code {
|
||||
private RenderFragment header = @<span>My App</span>;
|
||||
private RenderFragment navMenu = @<div>
|
||||
<FluentNavLink Href="/">Home</FluentNavLink>
|
||||
</div>;
|
||||
private RenderFragment body = @<div>@Body</div>;
|
||||
}
|
||||
```
|
||||
|
||||
## _Imports.razor
|
||||
|
||||
Add this to your `_Imports.razor`:
|
||||
|
||||
```razor
|
||||
@using Microsoft.FluentUI.AspNetCore.Components
|
||||
@using Icons = Microsoft.FluentUI.AspNetCore.Components.Icons
|
||||
```
|
||||
|
||||
## Static Web Assets
|
||||
|
||||
No manual `<link>` or `<script>` tags are needed. The library uses:
|
||||
- **CSS**: `reboot.css` (normalization) + component-scoped CSS — auto-loaded via static web assets
|
||||
- **JS**: `lib.module.js` — auto-loaded via Blazor's JS initializer system
|
||||
- Component-specific JS (e.g. DataGrid, Autocomplete) — lazy-loaded on demand
|
||||
|
||||
All served from `_content/Microsoft.FluentUI.AspNetCore.Components/`.
|
||||
|
||||
## Services Registered
|
||||
|
||||
Services automatically registered by `AddFluentUIComponents()`:
|
||||
|
||||
| Service | Implementation | Purpose |
|
||||
|---|---|---|
|
||||
| `GlobalState` | `GlobalState` | Shared application state |
|
||||
| `IToastService` | `ToastService` | Toast notifications (needs `FluentToastProvider`) |
|
||||
| `IDialogService` | `DialogService` | Dialogs and panels (needs `FluentDialogProvider`) |
|
||||
| `IMessageService` | `MessageService` | Message bars (needs `FluentMessageBarProvider`) |
|
||||
| `IKeyCodeService` | `KeyCodeService` | Keyboard shortcuts (needs `FluentKeyCodeProvider`) |
|
||||
| `IMenuService` | `MenuService` | Context menus |
|
||||
| `ITooltipService` | `TooltipService` | Tooltips (needs `FluentTooltipProvider`, opt-in via `UseTooltipServiceProvider`) |
|
||||
103
skills/fluentui-blazor/references/THEMING.md
Normal file
103
skills/fluentui-blazor/references/THEMING.md
Normal file
@@ -0,0 +1,103 @@
|
||||
# Theming
|
||||
|
||||
## FluentDesignTheme (recommended)
|
||||
|
||||
The primary theming component. Place it at the root of your app.
|
||||
|
||||
```razor
|
||||
<FluentDesignTheme Mode="DesignThemeModes.System"
|
||||
OfficeColor="OfficeColor.Teams"
|
||||
StorageName="mytheme" />
|
||||
```
|
||||
|
||||
### Parameters
|
||||
|
||||
| Parameter | Type | Default | Description |
|
||||
|---|---|---|---|
|
||||
| `Mode` | `DesignThemeModes` | `System` | `Light`, `Dark`, or `System` (follows OS) |
|
||||
| `CustomColor` | `string?` | null | Hex accent color (e.g. `"#0078D4"`) |
|
||||
| `OfficeColor` | `OfficeColor?` | null | Preset accent: `Teams`, `Word`, `Excel`, `PowerPoint`, `Outlook`, `OneNote` |
|
||||
| `NeutralBaseColor` | `string?` | null | Neutral palette base hex color |
|
||||
| `StorageName` | `string?` | null | Persist theme to localStorage under this key |
|
||||
| `Direction` | `LocalizationDirection?` | null | `Ltr` or `Rtl` |
|
||||
| `OnLuminanceChanged` | `EventCallback<LuminanceChangedEventArgs>` | | Fired when dark/light mode changes |
|
||||
| `OnLoaded` | `EventCallback<LoadedEventArgs>` | | Fired when theme is loaded from storage |
|
||||
|
||||
### Two-way binding
|
||||
|
||||
```razor
|
||||
<FluentDesignTheme @bind-Mode="@themeMode"
|
||||
@bind-OfficeColor="@officeColor"
|
||||
@bind-CustomColor="@customColor"
|
||||
StorageName="mytheme" />
|
||||
|
||||
<FluentSelect Items="@(Enum.GetValues<DesignThemeModes>())"
|
||||
@bind-SelectedOption="@themeMode"
|
||||
OptionText="@(m => m.ToString())" />
|
||||
|
||||
@code {
|
||||
private DesignThemeModes themeMode = DesignThemeModes.System;
|
||||
private OfficeColor? officeColor = OfficeColor.Teams;
|
||||
private string? customColor;
|
||||
}
|
||||
```
|
||||
|
||||
### Important: JS interop dependency
|
||||
|
||||
`FluentDesignTheme` uses JavaScript interop internally. It will NOT work during server-side pre-rendering. If you need to react to theme changes:
|
||||
|
||||
```csharp
|
||||
// Use OnAfterRenderAsync, NOT OnInitialized
|
||||
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||
{
|
||||
if (firstRender)
|
||||
{
|
||||
// Safe to interact with design tokens here
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## FluentDesignSystemProvider (advanced)
|
||||
|
||||
For scoping design tokens to a subtree of the component tree. Provides 50+ CSS custom properties.
|
||||
|
||||
```razor
|
||||
<FluentDesignSystemProvider AccentBaseColor="#0078D4"
|
||||
NeutralBaseColor="#808080"
|
||||
BaseLayerLuminance="0.95">
|
||||
<FluentButton Appearance="Appearance.Accent">Themed Button</FluentButton>
|
||||
</FluentDesignSystemProvider>
|
||||
```
|
||||
|
||||
## Design Token Classes (DI-based, advanced)
|
||||
|
||||
For programmatic token control via dependency injection. Each token is a generated service.
|
||||
|
||||
```csharp
|
||||
@inject AccentBaseColor AccentBaseColor
|
||||
|
||||
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||
{
|
||||
if (firstRender)
|
||||
{
|
||||
// Set token for a specific element
|
||||
await AccentBaseColor.SetValueFor(myElement, "#FF0000".ToSwatch());
|
||||
|
||||
// Read token value
|
||||
var currentColor = await AccentBaseColor.GetValueFor(myElement);
|
||||
|
||||
// Remove override
|
||||
await AccentBaseColor.DeleteValueFor(myElement);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Available DesignThemeModes
|
||||
|
||||
- `DesignThemeModes.Light` — light theme
|
||||
- `DesignThemeModes.Dark` — dark theme
|
||||
- `DesignThemeModes.System` — follows OS preference
|
||||
|
||||
## Available OfficeColor presets
|
||||
|
||||
`Teams`, `Word`, `Excel`, `PowerPoint`, `Outlook`, `OneNote`, `Loop`, `Planner`, `SharePoint`, `Stream`, `Sway`, `Viva`, `VivaEngage`, `VivaInsights`, `VivaLearning`, `VivaTopics`.
|
||||
Reference in New Issue
Block a user