[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M69BH43MCD88XA0W8ZB2YV5W":3,"skill-same:01M69BH43MCD88XA0W8ZB2YV5W":87},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":23,"publishedAt":44,"linkOnly":45,"markdownContent":46,"markdownBody":47,"frontMatter":48,"refName":49,"commitSha":50,"skillDirectory":51,"forksCount":52,"repositoryHtmlUrl":53,"repositoryHomepageUrl":54,"ownerHtmlUrl":55,"ownerBlogUrl":56,"ownerDescription":57,"updatedAt":58,"install":59,"resources":72},"01M69BH43MCD88XA0W8ZB2YV5W","Fluent UI Blazor v5 — Usage Guide",null,"Provides accurate coding patterns for building Blazor applications with the Microsoft.FluentUI.AspNetCore.Components v5 NuGet package. Covers service registration, theming (CSS-based, no FluentDesignTheme), layout, navigation, dialogs, data grid, forms, icons, and common pitfalls.","microsoft\u002Ffluentui-blazor","microsoft","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F6154722?v=4","01M698VYDXZ6JW5WH3CRV650R8","Microsoft","01M69BGP6WDMXWAYKV68NV16H6",4861,"MIT","https:\u002F\u002Fgithub.com\u002Fmicrosoft\u002Ffluentui-blazor\u002Fblob\u002Fdev\u002Fexamples\u002FDemo\u002FFluentUI.Demo.Client\u002Fwwwroot\u002Fskills\u002Ffluentui-blazor-usage\u002FSKILL.md",[18],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000032","设计师","PROFESSION","适用职业",[24,25,26,5,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,9],"usage","fluent","blazor","ui","guide","common","for","pitfalls","common pitfalls","layout","forms","coding patterns","patterns","registration","css","coding","data","fluentui","icons","components","2026-11-10 10:12:30",false,"---\nname: Fluent UI Blazor v5 — Usage Guide\ndescription: >\n  Provides accurate coding patterns for building Blazor applications with the\n  Microsoft.FluentUI.AspNetCore.Components v5 NuGet package. Covers service\n  registration, theming (CSS-based, no FluentDesignTheme), layout, navigation,\n  dialogs, data grid, forms, icons, and common pitfalls.\n---\n\n# Fluent UI Blazor v5 — Usage Skill\n\nThis skill helps AI assistants generate **correct, idiomatic code** for\napplications that consume the `Microsoft.FluentUI.AspNetCore.Components`\n**v5** NuGet package. v5 targets **.NET 9+** and wraps\n`@fluentui\u002Fweb-components` v3.\n\n> **Critical**: v5 is a major rewrite. Many v4 APIs are removed or renamed.\n> Always verify patterns against this skill before answering.\n\n---\n\n## Quick Setup Checklist\n\n```csharp\n\u002F\u002F Program.cs\nbuilder.Services.AddFluentUIComponents();\n```\n\n```razor\n@* App.razor \u002F MainLayout.razor — add providers once at root *@\n\u003CFluentProviders \u002F>\n```\n\n```html\n\u003C!-- index.html \u002F _Host.cshtml — required CSS & JS -->\n\u003Clink href=\"_content\u002FMicrosoft.FluentUI.AspNetCore.Components\u002Fcss\u002Fdefault-fuib.css\"\n      rel=\"stylesheet\" \u002F>\n```\n\nThe `\u003CFluentProviders \u002F>` component replaces the need to manually add\n`\u003CFluentDialogProvider \u002F>`, `\u003CFluentTooltipProvider \u002F>`, and\n`\u003CFluentKeyCodeProvider \u002F>` separately.\n\n---\n\n## Key v5 Differences from v4\n\n| Area | v4 | v5 |\n|---|---|---|\n| Target framework | net8.0 | net9.0 \u002F net10.0 |\n| Theming | `\u003CFluentDesignTheme>` component | CSS custom properties via JS (`setTheme`), `body[data-theme]` attribute |\n| Toast \u002F MessageBar | `IToastService`, `IMessageService` | **Removed** — use `FluentToast` component directly or custom solution |\n| Navigation | `FluentNavMenu`, `FluentNavLink`, `FluentNavGroup` | `FluentNav`, `FluentNavItem`, `FluentNavCategory`, `FluentNavSectionHeader` |\n| Dialog API | `IDialogContentComponent\u003CT>`, complex reference | Simplified: `IDialogService.ShowDialogAsync\u003CTDialog>(DialogOptions)` |\n| List binding | `FluentListBase\u003CTOption>`, `SelectedOptions` | `FluentListBase\u003CTOption, TValue>`, `SelectedItems` |\n| Progress | `FluentProgress` | `FluentProgressBar` (`FluentProgress` = obsolete shim) |\n| Appearance enum | `Appearance.Accent`, `.Stealth`, etc. | `ButtonAppearance.Primary`, `.Transparent`, etc. |\n| Switch | `CheckedMessage`\u002F`UncheckedMessage` child content | Removed — label only via `Label` parameter |\n| Component base | Property injection | Constructor injection of `LibraryConfiguration` |\n| Margin \u002F Padding | Not on components | Available on **every** component via `Margin` and `Padding` parameters |\n| Icons packages | Separate NuGet packages | Bundled (core icons), with optional extended packages |\n\n---\n\n## Theming\n\nv5 replaces `\u003CFluentDesignTheme>` with a **JavaScript + CSS custom property** model.\n\n### Apply a theme\n\n```razor\n@inject IJSRuntime JSRuntime\n\n\u003CFluentButton OnClick=\"@SwitchTheme\">Toggle theme\u003C\u002FFluentButton>\n\n@code {\n    private async Task SwitchTheme()\n    {\n        await JSRuntime.InvokeVoidAsync(\"Blazor.theme.switchTheme\");\n    }\n}\n```\n\n### Detect current mode\n\n```javascript\n\u002F\u002F body[data-theme=\"dark\"] → dark mode\n\u002F\u002F body without data-theme  → light mode\nBlazor.theme.isDarkMode()   \u002F\u002F returns boolean\nBlazor.theme.isSystemDark() \u002F\u002F returns boolean\n```\n\n### Conditional rendering by theme\n\n```razor\n\u003CFluentIcon Class=\"hidden-if-light\"\n            Value=\"@(new Icons.Filled.Size20.WeatherSunny())\" \u002F>\n\u003CFluentIcon Class=\"hidden-if-dark\"\n            Value=\"@(new Icons.Filled.Size20.WeatherMoon())\" \u002F>\n```\n\n### CSS variables\n\nAll Fluent design tokens are available as CSS custom properties:\n`var(--colorBrandBackground)`, `var(--colorNeutralForeground1)`,\n`var(--fontSizeBase300)`, `var(--borderRadiusMedium)`, etc.\n\nC# constants are available via `StylesVariables` and `SystemColors`:\n\n```csharp\n\u002F\u002F In component styles\nstyle=\"@($\"background: {SystemColors.Neutral.Background1}\")\"\n\u002F\u002F Equivalent to: background: var(--colorNeutralBackground1);\n\nstyle=\"@($\"border-radius: {StylesVariables.Borders.Radius.Medium}\")\"\n\u002F\u002F Equivalent to: border-radius: var(--borderRadiusMedium);\n```\n\n---\n\n## Layout & Navigation\n\n### FluentLayout\n\n```razor\n\u003CFluentLayout>\n    \u003CFluentLayoutItem Area=\"LayoutArea.Header\">\n        \u003CFluentLayoutHamburger \u002F>\n        \u003Cspan>My App\u003C\u002Fspan>\n    \u003C\u002FFluentLayoutItem>\n\n    \u003CFluentLayoutItem Area=\"LayoutArea.Menu\">\n        \u003CFluentNav>\n            \u003CFluentNavItem Href=\"\u002F\" Icon=\"@(new Icons.Regular.Size20.Home())\">\n                Home\n            \u003C\u002FFluentNavItem>\n            \u003CFluentNavCategory Label=\"Settings\" Icon=\"@(new Icons.Regular.Size20.Settings())\">\n                \u003CFluentNavItem Href=\"\u002Fsettings\u002Fprofile\">Profile\u003C\u002FFluentNavItem>\n                \u003CFluentNavItem Href=\"\u002Fsettings\u002Faccount\">Account\u003C\u002FFluentNavItem>\n            \u003C\u002FFluentNavCategory>\n            \u003CFluentNavSectionHeader Label=\"Admin\" \u002F>\n            \u003CFluentNavItem Href=\"\u002Fadmin\">Dashboard\u003C\u002FFluentNavItem>\n        \u003C\u002FFluentNav>\n    \u003C\u002FFluentLayoutItem>\n\n    \u003CFluentLayoutItem Area=\"LayoutArea.Content\">\n        @Body\n    \u003C\u002FFluentLayoutItem>\n\n    \u003CFluentLayoutItem Area=\"LayoutArea.Footer\">\n        \u003Cspan>&copy; 2025\u003C\u002Fspan>\n    \u003C\u002FFluentLayoutItem>\n\u003C\u002FFluentLayout>\n```\n\n> **Common mistake**: Using `FluentNavMenu` \u002F `FluentNavLink` \u002F `FluentNavGroup` (v4 names). These do **not** exist in v5.\n\n---\n\n## Dialogs\n\n### Show a simple dialog\n\n```csharp\n@inject IDialogService DialogService\n\nprivate async Task OpenDialog()\n{\n    var options = new DialogOptions\n    {\n        Header = { Title = \"Confirm action\" },\n        Size = DialogSize.Medium,\n        Modal = true,\n    };\n\n    var result = await DialogService.ShowDialogAsync\u003CConfirmDialog>(options);\n    if (!result.Cancelled)\n    {\n        \u002F\u002F result.Value contains the returned data\n    }\n}\n```\n\n### Dialog component\n\n```razor\n@* ConfirmDialog.razor *@\n\u003Cp>Are you sure you want to proceed?\u003C\u002Fp>\n\u003CFluentButton Appearance=\"ButtonAppearance.Primary\"\n              OnClick=\"@Confirm\">Yes\u003C\u002FFluentButton>\n\u003CFluentButton OnClick=\"@Cancel\">No\u003C\u002FFluentButton>\n\n@code {\n    [CascadingParameter]\n    public IDialogInstance Dialog { get; set; } = default!;\n\n    private async Task Confirm()\n        => await Dialog.CloseAsync(DialogResult.Ok(true));\n\n    private async Task Cancel()\n        => await Dialog.CloseAsync(DialogResult.Cancel());\n}\n```\n\n### Show a drawer\n\n```csharp\nvar result = await DialogService.ShowDrawerAsync\u003CDrawerContent>(options =>\n{\n    options.Header.Title = \"Settings\";\n    options.Alignment = DialogAlignment.End;\n    options.Size = DialogSize.Small;\n});\n```\n\n### Pass parameters to the dialog component\n\n```csharp\nvar options = new DialogOptions\n{\n    Header = { Title = \"Edit item\" },\n    Parameters = new Dictionary\u003Cstring, object?>\n    {\n        [\"ItemId\"] = selectedItemId,\n        [\"ItemName\"] = selectedItemName,\n    },\n};\nawait DialogService.ShowDialogAsync\u003CEditDialog>(options);\n```\n\n> **Common mistake**: Implementing `IDialogContentComponent\u003CT>` (v4 pattern). In v5, dialog components are plain Razor components that receive `IDialogInstance` as a cascading parameter.\n\n---\n\n## Data Grid\n\n```razor\n\u003CFluentDataGrid Items=\"@people\" Pagination=\"@pagination\">\n    \u003CPropertyColumn Property=\"@(p => p.Name)\" Sortable=\"true\" \u002F>\n    \u003CPropertyColumn Property=\"@(p => p.Email)\" \u002F>\n    \u003CTemplateColumn Title=\"Actions\">\n        \u003CFluentButton Size=\"ButtonSize.Small\"\n                      OnClick=\"@(() => Edit(context))\">\n            Edit\n        \u003C\u002FFluentButton>\n    \u003C\u002FTemplateColumn>\n\u003C\u002FFluentDataGrid>\n\n\u003CFluentPaginator State=\"@pagination\" \u002F>\n\n@code {\n    private IQueryable\u003CPerson> people = GetPeople().AsQueryable();\n    private PaginationState pagination = new() { ItemsPerPage = 10 };\n}\n```\n\n### Remote data with ItemsProvider\n\n```csharp\n\u003CFluentDataGrid ItemsProvider=\"@dataProvider\" Virtualize=\"true\" ItemSize=\"46\">\n    \u003CPropertyColumn Property=\"@(p => p.Name)\" Sortable=\"true\" \u002F>\n\u003C\u002FFluentDataGrid>\n\n@code {\n    private GridItemsProvider\u003CPerson> dataProvider = default!;\n\n    protected override void OnInitialized()\n    {\n        dataProvider = async request =>\n        {\n            var result = await Http.GetFromJsonAsync\u003CPagedResult\u003CPerson>>(\n                $\"api\u002Fpeople?start={request.StartIndex}&count={request.Count}\");\n            return GridItemsProviderResult.From(result!.Items, result.TotalCount);\n        };\n    }\n}\n```\n\nSee [DATAGRID.md](references\u002FDATAGRID.md) for advanced patterns (EF adapter,\nOData, column options, resize, custom sort).\n\n---\n\n## Forms & Input Components\n\nv5 input components extend `InputBase\u003CTValue>` and implement `IFluentField`,\nproviding built-in form validation integration.\n\n```razor\n\u003CEditForm Model=\"@model\" OnValidSubmit=\"@Submit\">\n    \u003CDataAnnotationsValidator \u002F>\n\n    \u003CFluentTextField @bind-Value=\"model.Name\"\n                     Label=\"Name\"\n                     Required=\"true\" \u002F>\n\n    \u003CFluentNumberField @bind-Value=\"model.Age\"\n                       Label=\"Age\"\n                       Min=\"0\" Max=\"150\" \u002F>\n\n    \u003CFluentSelect TOption=\"string\"\n                  TValue=\"string\"\n                  Items=\"@countries\"\n                  @bind-Value=\"model.Country\"\n                  OptionText=\"@(c => c)\"\n                  OptionValue=\"@(c => c)\"\n                  Label=\"Country\" \u002F>\n\n    \u003CFluentCheckbox @bind-Value=\"model.AcceptTerms\"\n                    Label=\"I accept the terms\" \u002F>\n\n    \u003CFluentButton Type=\"ButtonType.Submit\"\n                  Appearance=\"ButtonAppearance.Primary\">\n        Submit\n    \u003C\u002FFluentButton>\n\u003C\u002FEditForm>\n```\n\n### List components — two type parameters\n\nAll list-based components (`FluentSelect`, `FluentCombobox`, `FluentListbox`)\nnow take **two** type parameters: `TOption` (the item type) and `TValue` (the\nbound value type).\n\n```razor\n\u003CFluentSelect TOption=\"Country\"\n              TValue=\"int\"\n              Items=\"@countries\"\n              @bind-Value=\"model.CountryId\"\n              OptionText=\"@(c => c.Name)\"\n              OptionValue=\"@(c => c.Id)\"\n              Label=\"Country\" \u002F>\n\n@* Multiple selection *@\n\u003CFluentListbox TOption=\"string\"\n               TValue=\"string\"\n               Items=\"@tags\"\n               Multiple=\"true\"\n               SelectedItems=\"@selectedTags\"\n               SelectedItemsChanged=\"@(items => selectedTags = items)\"\n               OptionText=\"@(t => t)\"\n               OptionValue=\"@(t => t)\" \u002F>\n```\n\n> **Common mistake**: Using `SelectedOptions` or `SelectedOptionsChanged` (v4 names). In v5, use `SelectedItems` \u002F `SelectedItemsChanged`.\n\n---\n\n## Icons\n\nIcons are instantiated as objects and passed via `Value`, `IconStart`, or\n`IconEnd` parameters:\n\n```razor\n@* Standalone icon *@\n\u003CFluentIcon Value=\"@(new Icons.Regular.Size24.Add())\" \u002F>\n\n@* Icon with color *@\n\u003CFluentIcon Value=\"@(new Icons.Filled.Size20.Heart().WithColor(\"red\"))\" \u002F>\n\n@* Icon in a button *@\n\u003CFluentButton IconStart=\"@(new Icons.Regular.Size20.Add())\"\n              Appearance=\"ButtonAppearance.Primary\">\n    Add item\n\u003C\u002FFluentButton>\n\n@* Icon from image URL *@\n\u003CFluentIcon Value=\"@Icon.FromImageUrl(\"\u002Fimages\u002Flogo.png\")\" \u002F>\n```\n\nIcon naming: `Icons.{Variant}.{Size}.{Name}`\n- Variants: `Regular`, `Filled`\n- Sizes: `Size16`, `Size20`, `Size24`, `Size28`, `Size32`, `Size48`\n\n---\n\n## Margin & Padding (NEW in v5)\n\nEvery component supports `Margin` and `Padding` parameters using a\nspacing-utility syntax:\n\n```razor\n\u003CFluentCard Margin=\"Margin.All4\" Padding=\"Padding.Horizontal3 Padding.Vertical2\">\n    Content with spacing\n\u003C\u002FFluentCard>\n```\n\n---\n\n## Common Pitfalls\n\n1. **Missing `\u003CFluentProviders \u002F>`** — Dialogs, tooltips, and keyboard shortcuts\n   will silently fail without this component in your layout.\n2. **Using v4 component names** — `FluentNavMenu` → `FluentNav`,\n   `FluentProgress` → `FluentProgressBar`, `FluentDesignTheme` → removed.\n3. **Using `IToastService`** — Toast service does not exist in v5.\n4. **`SelectedOptions` on lists** — Renamed to `SelectedItems`.\n5. **Single type parameter on lists** — `FluentSelect\u003Cstring>` is v4.\n   v5 requires `FluentSelect\u003CTOption, TValue>`.\n6. **`Appearance.Accent`** — Use `ButtonAppearance.Primary` instead.\n7. **Targeting net8.0** — v5 requires net9.0 or later.\n8. **Implementing `IDialogContentComponent`** — Not needed in v5. Dialog components\n   are plain Razor components receiving `IDialogInstance` as a cascading parameter.\n\n---\n\n## Reference Files\n\n- [SETUP.md](references\u002FSETUP.md) — Full setup guide for Blazor Server, WebAssembly, and Auto modes\n- [DATAGRID.md](references\u002FDATAGRID.md) — Advanced data grid patterns\n- [THEMING.md](references\u002FTHEMING.md) — Detailed theming, design tokens, and CSS variables reference\n","# Fluent UI Blazor v5 — Usage Skill\n\nThis skill helps AI assistants generate **correct, idiomatic code** for\napplications that consume the `Microsoft.FluentUI.AspNetCore.Components`\n**v5** NuGet package. v5 targets **.NET 9+** and wraps\n`@fluentui\u002Fweb-components` v3.\n\n> **Critical**: v5 is a major rewrite. Many v4 APIs are removed or renamed.\n> Always verify patterns against this skill before answering.\n\n---\n\n## Quick Setup Checklist\n\n```csharp\n\u002F\u002F Program.cs\nbuilder.Services.AddFluentUIComponents();\n```\n\n```razor\n@* App.razor \u002F MainLayout.razor — add providers once at root *@\n\u003CFluentProviders \u002F>\n```\n\n```html\n\u003C!-- index.html \u002F _Host.cshtml — required CSS & JS -->\n\u003Clink href=\"_content\u002FMicrosoft.FluentUI.AspNetCore.Components\u002Fcss\u002Fdefault-fuib.css\"\n      rel=\"stylesheet\" \u002F>\n```\n\nThe `\u003CFluentProviders \u002F>` component replaces the need to manually add\n`\u003CFluentDialogProvider \u002F>`, `\u003CFluentTooltipProvider \u002F>`, and\n`\u003CFluentKeyCodeProvider \u002F>` separately.\n\n---\n\n## Key v5 Differences from v4\n\n| Area | v4 | v5 |\n|---|---|---|\n| Target framework | net8.0 | net9.0 \u002F net10.0 |\n| Theming | `\u003CFluentDesignTheme>` component | CSS custom properties via JS (`setTheme`), `body[data-theme]` attribute |\n| Toast \u002F MessageBar | `IToastService`, `IMessageService` | **Removed** — use `FluentToast` component directly or custom solution |\n| Navigation | `FluentNavMenu`, `FluentNavLink`, `FluentNavGroup` | `FluentNav`, `FluentNavItem`, `FluentNavCategory`, `FluentNavSectionHeader` |\n| Dialog API | `IDialogContentComponent\u003CT>`, complex reference | Simplified: `IDialogService.ShowDialogAsync\u003CTDialog>(DialogOptions)` |\n| List binding | `FluentListBase\u003CTOption>`, `SelectedOptions` | `FluentListBase\u003CTOption, TValue>`, `SelectedItems` |\n| Progress | `FluentProgress` | `FluentProgressBar` (`FluentProgress` = obsolete shim) |\n| Appearance enum | `Appearance.Accent`, `.Stealth`, etc. | `ButtonAppearance.Primary`, `.Transparent`, etc. |\n| Switch | `CheckedMessage`\u002F`UncheckedMessage` child content | Removed — label only via `Label` parameter |\n| Component base | Property injection | Constructor injection of `LibraryConfiguration` |\n| Margin \u002F Padding | Not on components | Available on **every** component via `Margin` and `Padding` parameters |\n| Icons packages | Separate NuGet packages | Bundled (core icons), with optional extended packages |\n\n---\n\n## Theming\n\nv5 replaces `\u003CFluentDesignTheme>` with a **JavaScript + CSS custom property** model.\n\n### Apply a theme\n\n```razor\n@inject IJSRuntime JSRuntime\n\n\u003CFluentButton OnClick=\"@SwitchTheme\">Toggle theme\u003C\u002FFluentButton>\n\n@code {\n    private async Task SwitchTheme()\n    {\n        await JSRuntime.InvokeVoidAsync(\"Blazor.theme.switchTheme\");\n    }\n}\n```\n\n### Detect current mode\n\n```javascript\n\u002F\u002F body[data-theme=\"dark\"] → dark mode\n\u002F\u002F body without data-theme  → light mode\nBlazor.theme.isDarkMode()   \u002F\u002F returns boolean\nBlazor.theme.isSystemDark() \u002F\u002F returns boolean\n```\n\n### Conditional rendering by theme\n\n```razor\n\u003CFluentIcon Class=\"hidden-if-light\"\n            Value=\"@(new Icons.Filled.Size20.WeatherSunny())\" \u002F>\n\u003CFluentIcon Class=\"hidden-if-dark\"\n            Value=\"@(new Icons.Filled.Size20.WeatherMoon())\" \u002F>\n```\n\n### CSS variables\n\nAll Fluent design tokens are available as CSS custom properties:\n`var(--colorBrandBackground)`, `var(--colorNeutralForeground1)`,\n`var(--fontSizeBase300)`, `var(--borderRadiusMedium)`, etc.\n\nC# constants are available via `StylesVariables` and `SystemColors`:\n\n```csharp\n\u002F\u002F In component styles\nstyle=\"@($\"background: {SystemColors.Neutral.Background1}\")\"\n\u002F\u002F Equivalent to: background: var(--colorNeutralBackground1);\n\nstyle=\"@($\"border-radius: {StylesVariables.Borders.Radius.Medium}\")\"\n\u002F\u002F Equivalent to: border-radius: var(--borderRadiusMedium);\n```\n\n---\n\n## Layout & Navigation\n\n### FluentLayout\n\n```razor\n\u003CFluentLayout>\n    \u003CFluentLayoutItem Area=\"LayoutArea.Header\">\n        \u003CFluentLayoutHamburger \u002F>\n        \u003Cspan>My App\u003C\u002Fspan>\n    \u003C\u002FFluentLayoutItem>\n\n    \u003CFluentLayoutItem Area=\"LayoutArea.Menu\">\n        \u003CFluentNav>\n            \u003CFluentNavItem Href=\"\u002F\" Icon=\"@(new Icons.Regular.Size20.Home())\">\n                Home\n            \u003C\u002FFluentNavItem>\n            \u003CFluentNavCategory Label=\"Settings\" Icon=\"@(new Icons.Regular.Size20.Settings())\">\n                \u003CFluentNavItem Href=\"\u002Fsettings\u002Fprofile\">Profile\u003C\u002FFluentNavItem>\n                \u003CFluentNavItem Href=\"\u002Fsettings\u002Faccount\">Account\u003C\u002FFluentNavItem>\n            \u003C\u002FFluentNavCategory>\n            \u003CFluentNavSectionHeader Label=\"Admin\" \u002F>\n            \u003CFluentNavItem Href=\"\u002Fadmin\">Dashboard\u003C\u002FFluentNavItem>\n        \u003C\u002FFluentNav>\n    \u003C\u002FFluentLayoutItem>\n\n    \u003CFluentLayoutItem Area=\"LayoutArea.Content\">\n        @Body\n    \u003C\u002FFluentLayoutItem>\n\n    \u003CFluentLayoutItem Area=\"LayoutArea.Footer\">\n        \u003Cspan>&copy; 2025\u003C\u002Fspan>\n    \u003C\u002FFluentLayoutItem>\n\u003C\u002FFluentLayout>\n```\n\n> **Common mistake**: Using `FluentNavMenu` \u002F `FluentNavLink` \u002F `FluentNavGroup` (v4 names). These do **not** exist in v5.\n\n---\n\n## Dialogs\n\n### Show a simple dialog\n\n```csharp\n@inject IDialogService DialogService\n\nprivate async Task OpenDialog()\n{\n    var options = new DialogOptions\n    {\n        Header = { Title = \"Confirm action\" },\n        Size = DialogSize.Medium,\n        Modal = true,\n    };\n\n    var result = await DialogService.ShowDialogAsync\u003CConfirmDialog>(options);\n    if (!result.Cancelled)\n    {\n        \u002F\u002F result.Value contains the returned data\n    }\n}\n```\n\n### Dialog component\n\n```razor\n@* ConfirmDialog.razor *@\n\u003Cp>Are you sure you want to proceed?\u003C\u002Fp>\n\u003CFluentButton Appearance=\"ButtonAppearance.Primary\"\n              OnClick=\"@Confirm\">Yes\u003C\u002FFluentButton>\n\u003CFluentButton OnClick=\"@Cancel\">No\u003C\u002FFluentButton>\n\n@code {\n    [CascadingParameter]\n    public IDialogInstance Dialog { get; set; } = default!;\n\n    private async Task Confirm()\n        => await Dialog.CloseAsync(DialogResult.Ok(true));\n\n    private async Task Cancel()\n        => await Dialog.CloseAsync(DialogResult.Cancel());\n}\n```\n\n### Show a drawer\n\n```csharp\nvar result = await DialogService.ShowDrawerAsync\u003CDrawerContent>(options =>\n{\n    options.Header.Title = \"Settings\";\n    options.Alignment = DialogAlignment.End;\n    options.Size = DialogSize.Small;\n});\n```\n\n### Pass parameters to the dialog component\n\n```csharp\nvar options = new DialogOptions\n{\n    Header = { Title = \"Edit item\" },\n    Parameters = new Dictionary\u003Cstring, object?>\n    {\n        [\"ItemId\"] = selectedItemId,\n        [\"ItemName\"] = selectedItemName,\n    },\n};\nawait DialogService.ShowDialogAsync\u003CEditDialog>(options);\n```\n\n> **Common mistake**: Implementing `IDialogContentComponent\u003CT>` (v4 pattern). In v5, dialog components are plain Razor components that receive `IDialogInstance` as a cascading parameter.\n\n---\n\n## Data Grid\n\n```razor\n\u003CFluentDataGrid Items=\"@people\" Pagination=\"@pagination\">\n    \u003CPropertyColumn Property=\"@(p => p.Name)\" Sortable=\"true\" \u002F>\n    \u003CPropertyColumn Property=\"@(p => p.Email)\" \u002F>\n    \u003CTemplateColumn Title=\"Actions\">\n        \u003CFluentButton Size=\"ButtonSize.Small\"\n                      OnClick=\"@(() => Edit(context))\">\n            Edit\n        \u003C\u002FFluentButton>\n    \u003C\u002FTemplateColumn>\n\u003C\u002FFluentDataGrid>\n\n\u003CFluentPaginator State=\"@pagination\" \u002F>\n\n@code {\n    private IQueryable\u003CPerson> people = GetPeople().AsQueryable();\n    private PaginationState pagination = new() { ItemsPerPage = 10 };\n}\n```\n\n### Remote data with ItemsProvider\n\n```csharp\n\u003CFluentDataGrid ItemsProvider=\"@dataProvider\" Virtualize=\"true\" ItemSize=\"46\">\n    \u003CPropertyColumn Property=\"@(p => p.Name)\" Sortable=\"true\" \u002F>\n\u003C\u002FFluentDataGrid>\n\n@code {\n    private GridItemsProvider\u003CPerson> dataProvider = default!;\n\n    protected override void OnInitialized()\n    {\n        dataProvider = async request =>\n        {\n            var result = await Http.GetFromJsonAsync\u003CPagedResult\u003CPerson>>(\n                $\"api\u002Fpeople?start={request.StartIndex}&count={request.Count}\");\n            return GridItemsProviderResult.From(result!.Items, result.TotalCount);\n        };\n    }\n}\n```\n\nSee [DATAGRID.md](references\u002FDATAGRID.md) for advanced patterns (EF adapter,\nOData, column options, resize, custom sort).\n\n---\n\n## Forms & Input Components\n\nv5 input components extend `InputBase\u003CTValue>` and implement `IFluentField`,\nproviding built-in form validation integration.\n\n```razor\n\u003CEditForm Model=\"@model\" OnValidSubmit=\"@Submit\">\n    \u003CDataAnnotationsValidator \u002F>\n\n    \u003CFluentTextField @bind-Value=\"model.Name\"\n                     Label=\"Name\"\n                     Required=\"true\" \u002F>\n\n    \u003CFluentNumberField @bind-Value=\"model.Age\"\n                       Label=\"Age\"\n                       Min=\"0\" Max=\"150\" \u002F>\n\n    \u003CFluentSelect TOption=\"string\"\n                  TValue=\"string\"\n                  Items=\"@countries\"\n                  @bind-Value=\"model.Country\"\n                  OptionText=\"@(c => c)\"\n                  OptionValue=\"@(c => c)\"\n                  Label=\"Country\" \u002F>\n\n    \u003CFluentCheckbox @bind-Value=\"model.AcceptTerms\"\n                    Label=\"I accept the terms\" \u002F>\n\n    \u003CFluentButton Type=\"ButtonType.Submit\"\n                  Appearance=\"ButtonAppearance.Primary\">\n        Submit\n    \u003C\u002FFluentButton>\n\u003C\u002FEditForm>\n```\n\n### List components — two type parameters\n\nAll list-based components (`FluentSelect`, `FluentCombobox`, `FluentListbox`)\nnow take **two** type parameters: `TOption` (the item type) and `TValue` (the\nbound value type).\n\n```razor\n\u003CFluentSelect TOption=\"Country\"\n              TValue=\"int\"\n              Items=\"@countries\"\n              @bind-Value=\"model.CountryId\"\n              OptionText=\"@(c => c.Name)\"\n              OptionValue=\"@(c => c.Id)\"\n              Label=\"Country\" \u002F>\n\n@* Multiple selection *@\n\u003CFluentListbox TOption=\"string\"\n               TValue=\"string\"\n               Items=\"@tags\"\n               Multiple=\"true\"\n               SelectedItems=\"@selectedTags\"\n               SelectedItemsChanged=\"@(items => selectedTags = items)\"\n               OptionText=\"@(t => t)\"\n               OptionValue=\"@(t => t)\" \u002F>\n```\n\n> **Common mistake**: Using `SelectedOptions` or `SelectedOptionsChanged` (v4 names). In v5, use `SelectedItems` \u002F `SelectedItemsChanged`.\n\n---\n\n## Icons\n\nIcons are instantiated as objects and passed via `Value`, `IconStart`, or\n`IconEnd` parameters:\n\n```razor\n@* Standalone icon *@\n\u003CFluentIcon Value=\"@(new Icons.Regular.Size24.Add())\" \u002F>\n\n@* Icon with color *@\n\u003CFluentIcon Value=\"@(new Icons.Filled.Size20.Heart().WithColor(\"red\"))\" \u002F>\n\n@* Icon in a button *@\n\u003CFluentButton IconStart=\"@(new Icons.Regular.Size20.Add())\"\n              Appearance=\"ButtonAppearance.Primary\">\n    Add item\n\u003C\u002FFluentButton>\n\n@* Icon from image URL *@\n\u003CFluentIcon Value=\"@Icon.FromImageUrl(\"\u002Fimages\u002Flogo.png\")\" \u002F>\n```\n\nIcon naming: `Icons.{Variant}.{Size}.{Name}`\n- Variants: `Regular`, `Filled`\n- Sizes: `Size16`, `Size20`, `Size24`, `Size28`, `Size32`, `Size48`\n\n---\n\n## Margin & Padding (NEW in v5)\n\nEvery component supports `Margin` and `Padding` parameters using a\nspacing-utility syntax:\n\n```razor\n\u003CFluentCard Margin=\"Margin.All4\" Padding=\"Padding.Horizontal3 Padding.Vertical2\">\n    Content with spacing\n\u003C\u002FFluentCard>\n```\n\n---\n\n## Common Pitfalls\n\n1. **Missing `\u003CFluentProviders \u002F>`** — Dialogs, tooltips, and keyboard shortcuts\n   will silently fail without this component in your layout.\n2. **Using v4 component names** — `FluentNavMenu` → `FluentNav`,\n   `FluentProgress` → `FluentProgressBar`, `FluentDesignTheme` → removed.\n3. **Using `IToastService`** — Toast service does not exist in v5.\n4. **`SelectedOptions` on lists** — Renamed to `SelectedItems`.\n5. **Single type parameter on lists** — `FluentSelect\u003Cstring>` is v4.\n   v5 requires `FluentSelect\u003CTOption, TValue>`.\n6. **`Appearance.Accent`** — Use `ButtonAppearance.Primary` instead.\n7. **Targeting net8.0** — v5 requires net9.0 or later.\n8. **Implementing `IDialogContentComponent`** — Not needed in v5. Dialog components\n   are plain Razor components receiving `IDialogInstance` as a cascading parameter.\n\n---\n\n## Reference Files\n\n- [SETUP.md](references\u002FSETUP.md) — Full setup guide for Blazor Server, WebAssembly, and Auto modes\n- [DATAGRID.md](references\u002FDATAGRID.md) — Advanced data grid patterns\n- [THEMING.md](references\u002FTHEMING.md) — Detailed theming, design tokens, and CSS variables reference\n",{"name":5,"description":7},"dev","f8af8e010001336012b3b681fa0f6b897c17340d","examples\u002FDemo\u002FFluentUI.Demo.Client\u002Fwwwroot\u002Fskills\u002Ffluentui-blazor-usage",494,"https:\u002F\u002Fgithub.com\u002Fmicrosoft\u002Ffluentui-blazor","https:\u002F\u002Fwww.fluentui-blazor.net","https:\u002F\u002Fgithub.com\u002Fmicrosoft","https:\u002F\u002Fopensource.microsoft.com","Open source projects and samples from Microsoft","2026-11-14 02:44:43",{"source":8,"skillName":5,"commands":60,"prompt":70,"zipAvailable":71},[61,64,67],{"tool":62,"command":63},"npx","npx skills add microsoft\u002Ffluentui-blazor --skill \"Fluent UI Blazor v5 — Usage Guide\"",{"tool":65,"command":66},"bunx","bunx skills add microsoft\u002Ffluentui-blazor --skill \"Fluent UI Blazor v5 — Usage Guide\"",{"tool":68,"command":69},"pnpm","pnpm dlx skills add microsoft\u002Ffluentui-blazor --skill \"Fluent UI Blazor v5 — Usage Guide\"","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fmicrosoft\u002Ffluentui-blazor\u002Fblob\u002Fdev\u002Fexamples\u002FDemo\u002FFluentUI.Demo.Client\u002Fwwwroot\u002Fskills\u002Ffluentui-blazor-usage\u002FSKILL.md",true,[73,79,83],{"path":74,"resourceType":75,"resourceTypeDesc":76,"sizeBytes":77,"sourceHtmlUrl":78},"references\u002FDATAGRID.md","REFERENCE","参考文档",7150,"https:\u002F\u002Fgithub.com\u002Fmicrosoft\u002Ffluentui-blazor\u002Fblob\u002Fdev\u002Fexamples\u002FDemo\u002FFluentUI.Demo.Client\u002Fwwwroot\u002Fskills\u002Ffluentui-blazor-usage\u002Freferences\u002FDATAGRID.md",{"path":80,"resourceType":75,"resourceTypeDesc":76,"sizeBytes":81,"sourceHtmlUrl":82},"references\u002FSETUP.md",3790,"https:\u002F\u002Fgithub.com\u002Fmicrosoft\u002Ffluentui-blazor\u002Fblob\u002Fdev\u002Fexamples\u002FDemo\u002FFluentUI.Demo.Client\u002Fwwwroot\u002Fskills\u002Ffluentui-blazor-usage\u002Freferences\u002FSETUP.md",{"path":84,"resourceType":75,"resourceTypeDesc":76,"sizeBytes":85,"sourceHtmlUrl":86},"references\u002FTHEMING.md",6804,"https:\u002F\u002Fgithub.com\u002Fmicrosoft\u002Ffluentui-blazor\u002Fblob\u002Fdev\u002Fexamples\u002FDemo\u002FFluentUI.Demo.Client\u002Fwwwroot\u002Fskills\u002Ffluentui-blazor-usage\u002Freferences\u002FTHEMING.md",[88,109],{"skillNo":89,"name":90,"nameZh":6,"description":91,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":92,"categories":93,"keywords":94,"publishedAt":44},"01M69BH0SCCR84AGCRPTVZH60B","update-dependencies","Update repository NuGet and NPM dependencies and lockfiles to the latest compatible versions, then validate library builds and bUnit tests. Use when asked to update or upgrade repository dependencies.","https:\u002F\u002Fgithub.com\u002Fmicrosoft\u002Ffluentui-blazor\u002Fblob\u002Fdev\u002F.github\u002Fskills\u002Fupdate-dependencies\u002FSKILL.md",[],[95,96,97,98,99,100,101,102,103,104,105,106,107,108],"update dependencies","update","dependencies","repository","validate","nuget","npm","library","use","upgrade","tests","true","latest","when",{"skillNo":110,"name":111,"nameZh":6,"description":112,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":113,"categories":114,"keywords":120,"publishedAt":44},"01M69BGSMHAPBMQSVJ6NNR85V7","csharp-naming-conventions","C# and .NET naming conventions, coding best practices, layout rules,\nunit testing, and Blazor component guidelines. Use when\nwriting, reviewing, or refactoring C# \u002F .NET \u002F Blazor code or writing \nunit tests with xUnit and bUnit.","https:\u002F\u002Fgithub.com\u002Fmicrosoft\u002Ffluentui-blazor\u002Fblob\u002Fdev\u002F.github\u002Fskills\u002Fcsharp-naming-conventions\u002FSKILL.md",[115],{"categoryNo":116,"categoryName":117,"taxonomyType":118,"taxonomyTypeDesc":119},"01JBSEEDCAT000000000000008","测试与质量","SCENARIO","使用场景",[121,122,123,124,125,126,108,127,105,33,128,103,129,39,130,26,131,132,133,134,135],"naming conventions","naming","csharp","csharp naming conventions","conventions","unit","testing","unit testing","xunit","refactoring","code","guidelines","unit tests","component","writing"]