diff --git a/.agents/plugins/marketplace.json b/.agents/plugins/marketplace.json index e38732b689..cd87107df9 100644 --- a/.agents/plugins/marketplace.json +++ b/.agents/plugins/marketplace.json @@ -75,7 +75,7 @@ { "name": "dotnet-blazor", "source": "./plugins/dotnet-blazor", - "description": "Skills for Blazor development: component authoring, interactivity, and web application patterns." + "description": "Skills for Blazor development: component authoring, interactivity, web application patterns, and Syncfusion Blazor Toolkit installation." }, { "name": "dotnet-winforms", diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index 898e7608b9..8142d073e8 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -9,7 +9,7 @@ "source": "./plugins/dotnet", "description": "C# language server (LSP) integration for coding agents and high-level .NET development skills." }, - { + { "name": "dotnet-advanced", "source": "./plugins/dotnet-advanced", "description": "Advanced .NET and C# skills for niche scenarios that are not part of the core dotnet plugin." @@ -38,7 +38,9 @@ "--yes", "--prerelease" ], - "tools": ["*"] + "tools": [ + "*" + ] } } }, @@ -85,7 +87,7 @@ { "name": "dotnet-blazor", "source": "./plugins/dotnet-blazor", - "description": "Skills for Blazor development: component authoring, interactivity, and web application patterns." + "description": "Skills for Blazor development: component authoring, interactivity, web application patterns, and Syncfusion Blazor Toolkit installation." }, { "name": "dotnet-winforms", @@ -98,4 +100,4 @@ "description": "Skills for new .NET 11 APIs and language features." } ] -} \ No newline at end of file +} diff --git a/.cursor-plugin/marketplace.json b/.cursor-plugin/marketplace.json index 121ae385c6..093a3c36a3 100644 --- a/.cursor-plugin/marketplace.json +++ b/.cursor-plugin/marketplace.json @@ -12,7 +12,7 @@ "source": "./plugins/dotnet", "description": "C# language server (LSP) integration for coding agents and high-level .NET development skills." }, - { + { "name": "dotnet-advanced", "source": "./plugins/dotnet-advanced", "description": "Advanced .NET and C# skills for niche scenarios that are not part of the core dotnet plugin." @@ -75,7 +75,7 @@ { "name": "dotnet-blazor", "source": "./plugins/dotnet-blazor", - "description": "Skills for Blazor development: component authoring, interactivity, and web application patterns." + "description": "Skills for Blazor development: component authoring, interactivity, web application patterns, and Syncfusion Blazor Toolkit installation." }, { "name": "dotnet-winforms", diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index c65cba0f7f..c2a4b1a889 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -93,6 +93,10 @@ /plugins/dotnet-blazor/ @dotnet/aspnet /tests/dotnet-blazor/ @dotnet/aspnet +# Syncfusion Blazor Toolkit install skill +/plugins/dotnet-blazor/skills/syncfusion-blazor-toolkit-install/ @dotnet/aspnetcore-syncfusion-vendors @sheiksyedm @Indhumathy-Loganathan @rajendranr-5483 @PrinceOliver +/tests/dotnet-blazor/syncfusion-blazor-toolkit-install/ @dotnet/aspnetcore-syncfusion-vendors @sheiksyedm @Indhumathy-Loganathan @rajendranr-5483 @PrinceOliver + # dotnet-winforms (Windows Forms development) /plugins/dotnet-winforms/ @KlausLoeffelmann @AbhitejJohn /tests/dotnet-winforms/ @KlausLoeffelmann @AbhitejJohn diff --git a/.github/plugin/marketplace.json b/.github/plugin/marketplace.json index 8f6a538ea7..7974ab7c22 100644 --- a/.github/plugin/marketplace.json +++ b/.github/plugin/marketplace.json @@ -72,7 +72,7 @@ { "name": "dotnet-blazor", "source": "./plugins/dotnet-blazor", - "description": "Skills for Blazor development: component authoring, interactivity, and web application patterns." + "description": "Skills for Blazor development: component authoring, interactivity, web application patterns, and Syncfusion Blazor Toolkit installation." }, { "name": "dotnet-winforms", diff --git a/README.md b/README.md index 78c47fd0f3..9460d6d027 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,7 @@ Plugin support is component-specific: | [dotnet-test](plugins/dotnet-test/) | Skills for running, generating, analyzing, and improving .NET tests: test execution, filtering, platform detection, coverage, testability, and MSTest workflows. | | [dotnet-test-migration](plugins/dotnet-test-migration/) | Skills and a GitHub Copilot orchestrator agent for migrating .NET test frameworks and platforms: MSTest and xUnit version upgrades, xUnit-to-MSTest conversion, and VSTest to Microsoft.Testing.Platform. | | [dotnet-aspnetcore](plugins/dotnet-aspnetcore/) | ASP.NET Core web development skills including middleware, endpoints, real-time communication, and API patterns. | -| [dotnet-blazor](plugins/dotnet-blazor/) | Skills for Blazor development: component authoring, interactivity, and web application patterns. | +| [dotnet-blazor](plugins/dotnet-blazor/) | Skills for Blazor development: component authoring, interactivity, web application patterns, and Syncfusion Blazor Toolkit installation. | | [dotnet-winforms](plugins/dotnet-winforms/) | Skills for Windows Forms development: project setup, UI design, data binding, accessibility, and modern .NET practices. | | [dotnet11](plugins/dotnet11/) | Skills for new .NET 11 APIs and language features. | diff --git a/eng/known-domains.txt b/eng/known-domains.txt index 4831600c8b..da3d52c28c 100644 --- a/eng/known-domains.txt +++ b/eng/known-domains.txt @@ -65,6 +65,7 @@ github.com/username testsmells.org # Community +github.com/syncfusion/blazor-toolkit github.com/JeremyKuhne github.com/Youssef1313/Combinatorial.MSTest ollama.com diff --git a/plugins/dotnet-blazor/.claude-plugin/plugin.json b/plugins/dotnet-blazor/.claude-plugin/plugin.json index 9ab06bea49..118cbdf53b 100644 --- a/plugins/dotnet-blazor/.claude-plugin/plugin.json +++ b/plugins/dotnet-blazor/.claude-plugin/plugin.json @@ -1,6 +1,8 @@ { "name": "dotnet-blazor", "version": "0.1.2", - "description": "Skills for Blazor development: component authoring, interactivity, and web application patterns.", - "skills": ["./skills/"] + "description": "Skills for Blazor development: component authoring, interactivity, web application patterns, and Syncfusion Blazor Toolkit installation.", + "skills": [ + "./skills/" + ] } diff --git a/plugins/dotnet-blazor/.codex-plugin/plugin.json b/plugins/dotnet-blazor/.codex-plugin/plugin.json index 9ab06bea49..118cbdf53b 100644 --- a/plugins/dotnet-blazor/.codex-plugin/plugin.json +++ b/plugins/dotnet-blazor/.codex-plugin/plugin.json @@ -1,6 +1,8 @@ { "name": "dotnet-blazor", "version": "0.1.2", - "description": "Skills for Blazor development: component authoring, interactivity, and web application patterns.", - "skills": ["./skills/"] + "description": "Skills for Blazor development: component authoring, interactivity, web application patterns, and Syncfusion Blazor Toolkit installation.", + "skills": [ + "./skills/" + ] } diff --git a/plugins/dotnet-blazor/plugin.json b/plugins/dotnet-blazor/plugin.json index 9ab06bea49..118cbdf53b 100644 --- a/plugins/dotnet-blazor/plugin.json +++ b/plugins/dotnet-blazor/plugin.json @@ -1,6 +1,8 @@ { "name": "dotnet-blazor", "version": "0.1.2", - "description": "Skills for Blazor development: component authoring, interactivity, and web application patterns.", - "skills": ["./skills/"] + "description": "Skills for Blazor development: component authoring, interactivity, web application patterns, and Syncfusion Blazor Toolkit installation.", + "skills": [ + "./skills/" + ] } diff --git a/plugins/dotnet-blazor/skills/syncfusion-blazor-toolkit-install/SKILL.md b/plugins/dotnet-blazor/skills/syncfusion-blazor-toolkit-install/SKILL.md new file mode 100644 index 0000000000..eeaec764c1 --- /dev/null +++ b/plugins/dotnet-blazor/skills/syncfusion-blazor-toolkit-install/SKILL.md @@ -0,0 +1,219 @@ +--- +license: MIT +name: syncfusion-blazor-toolkit-install +description: > + Install and register the open-source Syncfusion Blazor Toolkit package + (v2.0+), configure AddSyncfusionBlazorToolkit(), rely on SfThemeRoot and CSS + isolation for theming (no host fluent.min.css link), apply the interactive + render mode that matches the app topology (legacy Server, standalone WASM, + or a Blazor Web App), and account for namespace consolidation. + + USE FOR: Toolkit setup, package verification, theme model (SfThemeRoot / + CSS isolation), split-app registration, render-mode troubleshooting, + diagnosing an accidental commercial Syncfusion.Blazor install or license-key + prompt when the user wanted the open-source Toolkit, and migrating from + Toolkit 1.x to 2.0. + DO NOT USE FOR: component API details (use author-component), Blazor project + creation (use create-blazor-project), configuring commercial Syncfusion + components that the app actually uses, Hybrid/MAUI. +--- + +# Install Syncfusion Blazor Toolkit + +## Core Rules + +1. **Verify the target framework first.** `Syncfusion.Blazor.Toolkit` 2.0.0 targets `net8.0`, `net9.0`, and `net10.0`. Always check the project's `` before installation. On `net6.0`, `net7.0`, or older frameworks, NuGet restore fails with an incompatibility such as `NU1202` because the package has no compatible assets for those TFMs. Do not expect a later `CS0246` as the primary signal—fix the framework mismatch first. Do not proceed with Toolkit installation on unsupported frameworks. Recommend upgrading the application to .NET 8 or later first (for example with the `dotnet-upgrade` plugin), then continue with the installation steps. If the `` is unknown, read it before doing anything else. Never edit the TFM just to make the package install. +2. Use the exact package ID `Syncfusion.Blazor.Toolkit`. Prefer the latest 2.x stable release (2.0.0 or newer). Version 2.0.0 is **not source-compatible** with 1.0.2. +3. In every `Program.cs` that calls `AddSyncfusionBlazorToolkit()`, add `using Syncfusion.Blazor.Toolkit;` so the extension method is in scope. Call it before `builder.Build()`. +4. **Namespace consolidation (2.0 breaking change).** All public component types—including `SfButton`, `SfTextBox`, `SfChart`, calendars, dialogs, and spinner—live under the single root namespace `Syncfusion.Blazor.Toolkit`. Domain-specific namespaces (`Syncfusion.Blazor.Toolkit.Buttons`, `.Calendars`, `.Charts`, `.Inputs`, `.Popups`, `.Spinner`, etc.) were **removed** in 2.0. Add only: + ```razor + @using Syncfusion.Blazor.Toolkit + ``` + to `_Imports.razor` (and the equivalent `using` in C# files). That single import is enough for every public component type. A missing namespace produces Razor warning `RZ10012` and renders the tag as an unknown HTML element. `_Imports.razor` does not affect `Program.cs`. + + **Exception: `Syncfusion.Blazor.Toolkit.Data` is still shipped in 2.0.** The data-binding types `DataAdaptor`, `DataManager`, and `Query` live in `Syncfusion.Blazor.Toolkit.Data`, not the root. Add `@using Syncfusion.Blazor.Toolkit.Data` (or fully qualified names like `Syncfusion.Blazor.Toolkit.Data.DataManager`) only when code references those types; the component imports above do not bring them in. Do not assume `.Data` was removed like the other child namespaces. +5. **Theming (2.0 — no host theme stylesheet).** Do **not** link `fluent.min.css`, `highcontrast.min.css`, or per-component stylesheets under `_content/Syncfusion.Blazor.Toolkit/styles/`. Component styles use Blazor CSS isolation; the shared theme layer (`:root` tokens, base/utility styles, icon font, keyframes, dark/high-contrast/forced-colors) is emitted at render time by `SfThemeRoot`. Every consumer-facing root component renders `` as its previous sibling automatically—no extra consumer configuration is required when Toolkit components are present. Place an explicit `` only when theme emission is needed without a Toolkit component in the tree. Keep the template's own `app.css` / `{Project}.styles.css` links; do not replace the host file. +6. Use `@rendermode` only in a Blazor Web App. Legacy Blazor Server and standalone WebAssembly are already interactive and do not use render modes. In a Web App, **`-int Server`, `-int WebAssembly` and `-int Auto` are per-page** by default: `` has **no** directive unless you passed `-ai`. Only `-ai` (`--all-interactive`) is global (mode on `Routes` / `HeadOutlet`). Any Toolkit component that uses events, bindings, dialogs, calendar navigation, or button clicks must sit inside an **interactive boundary**: (a) the page's `@rendermode`, (b) an interactive **wrapper component** on an otherwise static SSR page, or (c) the inherited `Routes` mode in a global (`-ai`) app. The page itself does **not** have to be interactive—Blazor allows interactive children on a static page. +7. Toolkit components need `AddSyncfusionBlazorToolkit()` on **every host that renders them, including static SSR**. Without it the page returns HTTP 500 with `There is no registered service of type 'Syncfusion.Blazor.Toolkit.SyncfusionBlazorToolkitService'`. In a split Blazor Web App, register on the server and in `.Client`: prerendering runs `.Client` components on the server, so client-only registration still returns 500. +8. In a split Blazor Web App, the `.Client` project is not a standalone WASM app. Do not call `RootComponents.Add("#app")` there. Keep the `.AddAdditionalAssemblies(typeof(.Client._Imports).Assembly)` call the template puts on `MapRazorComponents()`; the server needs it to see `.Client` pages. It is unrelated to Toolkit, so never add, remove, or move it. +9. Do not add a commercial `Syncfusion.Blazor*` package to satisfy a Toolkit request. If the app already uses commercial components, leave those packages and `Syncfusion.Licensing.SyncfusionLicenseProvider.RegisterLicense(...)` in place. +10. Toolkit JavaScript is embedded in the NuGet package; do not add commercial script tags. +11. Keep this skill install-focused; use the references for details and troubleshooting. +12. **CSS isolation (2.0).** Component styles are scoped. App-level overrides that previously targeted unscoped toolkit class names (for example `.e-btn`) may need the `::deep` combinator or adjustment for isolation attributes. Review custom CSS after upgrading from 1.x. + +## Don'ts + +- Don't install the Toolkit on a .NET 6 or .NET 7 project, or when the `` has not been checked. Recommend upgrading to .NET 8 or later first. +- Don't treat `Syncfusion.Blazor` or component-specific commercial packages as Toolkit dependencies. +- Don't add external script tags or commercial Syncfusion license scripts; Toolkit JS is bundled with the package. +- Don't leave an interactive Toolkit control outside any interactive boundary (page `@rendermode`, interactive wrapper, or inherited `Routes` mode). A static SSR page is fine if a child wrapper owns the control and its handlers. +- Don't use this skill as a component API reference; consult the official Syncfusion Blazor Toolkit demos or documentation for API details. +- Don't use domain-specific `@using` directives from Toolkit 1.x (`Syncfusion.Blazor.Toolkit.Buttons`, `.Calendars`, etc.). They no longer exist in 2.0. +- Don't link `fluent.min.css`, `highcontrast.min.css`, or other `_content/Syncfusion.Blazor.Toolkit/styles/*.css` files in the host; 2.0 theming uses `SfThemeRoot` and CSS isolation. +- Don't replace or retype `Program.cs`, `App.razor`, `_Host.cshtml`, or `wwwroot/index.html`. Make only the additions shown below and leave every other template line (`UseExceptionHandler`, `UseHsts`, `MapStaticAssets`, `HeadOutlet`, `Routes`, render-mode directives, script tags) untouched. + +## Quick Decision Table + +Pick the **single** row that matches the app the user is on. The "Program.cs" columns say where `AddSyncfusionBlazorToolkit()` goes; the template's own endpoint calls stay as generated. + +| Scenario | Register in server `Program.cs` | Register in `.Client/Program.cs` | Host file (keep template CSS only) | Where interactive Toolkit components go | +| --- | --- | --- | --- | --- | +| Legacy Blazor Server (`_Host.cshtml`, net8.0+ only for Toolkit) | Yes | n/a | `_Host.cshtml` | Anywhere; already interactive, no `@rendermode` | +| Standalone Blazor WebAssembly | n/a | Yes, in the standalone `Program.cs`; it keeps its own `RootComponents.Add("#app")` | `wwwroot/index.html` | Anywhere; already interactive, no `@rendermode` | +| Web App `-int Server` (**per-page**, not global) | Yes | n/a (no `.Client` project) | `Components/App.razor` | Interactive boundary: page `@rendermode InteractiveServer` **or** interactive wrapper; pure static pages are display-only | +| Web App `-int Server -ai` (**global**) | Yes | n/a | `Components/App.razor` | Anywhere; inherits `InteractiveServer` from `Routes`. Do not add a different mode | +| Web App `-int WebAssembly` (**per-page**, not global) | Yes | Yes; **no** `RootComponents.Add` | `Components/App.razor` | Interactive boundary in `.Client` (page **or** wrapper with `@rendermode InteractiveWebAssembly`); server-project pages prerender then fail in the browser | +| Web App `-int WebAssembly -ai` (**global**) | Yes | Yes | `Components/App.razor` | In `.Client` only (inherits from `Routes`); server-project pages prerender then fail in the browser | +| Web App `-int Auto` (**per-page**, not global) | Yes | Yes; **no** `RootComponents.Add` | `Components/App.razor` | Interactive boundary in `.Client` (page **or** wrapper with `@rendermode InteractiveAuto`); server-project pages prerender then fail in the browser. First visit server, later cached WASM; a running component does not switch | +| Web App `-int Auto -ai` (**global**) | Yes | Yes | `Components/App.razor` | In `.Client` only (inherits from `Routes`); server-project pages prerender then fail in the browser | +| Web App `-int None` / static SSR page | Yes, if any Toolkit markup renders | n/a | `Components/App.razor` | Display-only Toolkit markup only; **never** components that use events, bindings, dialogs, or clicks | +| .NET MAUI Blazor Hybrid | **Out of scope** (see below) | n/a | n/a | n/a | + +Verified with `dotnet new blazor`: without `-ai`, `` carries no directive and only the sample `Counter.razor` has its own `@rendermode`. With `-ai`, `HeadOutlet` and `Routes` carry `@rendermode="Interactive..."`. See [Render modes explained](./references/render-modes.md). + +## Minimal Setup + +### Package + +```bash +dotnet add package Syncfusion.Blazor.Toolkit +``` + +Prefer the latest 2.x version (2.0.0 or newer). In a split Blazor Web App, install into the `.Client` project — the reference flows transitively to Server — by targeting the project file directly. From the solution directory: +```bash +dotnet add MyApp.Client/MyApp.Client.csproj package Syncfusion.Blazor.Toolkit +``` +Replace `MyApp` with the app's name (the generated project is named `.Client`, never literally `.Client`, so the SDK can't resolve it as a directory). Installing only into Server leaves `.Client` without the package, so `@using Syncfusion.Blazor.Toolkit` and `AddSyncfusionBlazorToolkit()` there will fail to compile. + +### Program.cs: make only these additions + +Every template (`-int Server`, `-int WebAssembly`, `-int Auto`) already generates its own `AddRazorComponents()`, `Map*` and `AddAdditionalAssemblies(...)` calls. **Do not retype or replace them.** Add **only** `using Syncfusion.Blazor.Toolkit;` and `builder.Services.AddSyncfusionBlazorToolkit();` (plus the same registration on `.Client` when the template has a Client project). Pasting a full sample `Program.cs` from docs is a common failure: it can drop `using .Components;` (`CS0246` on `App`), remove `UseExceptionHandler` / `UseHsts` / `UseHttpsRedirection`, drop static-asset mapping (`MapStaticAssets` on .NET 9+, `UseStaticFiles` on .NET 8), remove `.AddAdditionalAssemblies(...)` on WebAssembly/Auto hosts (Client routes stop resolving), or add Interactive Server services to a WebAssembly-only template. + +**Server `Program.cs`** (all three Web App templates and legacy Server). Add one `using` at the top and one line before `var app = builder.Build();`: + +```csharp +using Syncfusion.Blazor.Toolkit; // add at the top, with the other usings + +// ...the template's builder.Services.AddRazorComponents()... stays exactly as generated... + +builder.Services.AddSyncfusionBlazorToolkit(); // add just before builder.Build() + +var app = builder.Build(); +``` + +What the template already contains (leave it alone): + +| Template | `AddRazorComponents()` chain | `MapRazorComponents()` chain | +| --- | --- | --- | +| `-int Server` | `.AddInteractiveServerComponents()` | `.AddInteractiveServerRenderMode()` | +| `-int WebAssembly` | `.AddInteractiveWebAssemblyComponents()` | `.AddInteractiveWebAssemblyRenderMode()` and `.AddAdditionalAssemblies(typeof(.Client._Imports).Assembly)` | +| `-int Auto` | `.AddInteractiveServerComponents()` and `.AddInteractiveWebAssemblyComponents()` | `.AddInteractiveServerRenderMode()`, `.AddInteractiveWebAssemblyRenderMode()` and `.AddAdditionalAssemblies(...)` | + +Never mix these shapes. Do not add `AddInteractiveServerComponents()` to a WebAssembly template, or remove it from an Auto template; Toolkit does not need either change. + +**Blazor Web App `.Client/Program.cs`** (`-int WebAssembly`, `-int Auto`). The template already has `using Microsoft.AspNetCore.Components.WebAssembly.Hosting;`. Add the Toolkit using and one line before `await builder.Build().RunAsync();`: + +```csharp +using Microsoft.AspNetCore.Components.WebAssembly.Hosting; // already generated; keep it +using Syncfusion.Blazor.Toolkit; // add + +var builder = WebAssemblyHostBuilder.CreateDefault(args); + +builder.Services.AddSyncfusionBlazorToolkit(); // add + +await builder.Build().RunAsync(); +``` + +This project is not a standalone WASM app. The server owns `App.razor` and the host page has no `#app` element, so do not register a root component here. + +**Standalone Blazor WebAssembly `Program.cs`**. The template already contains the usings and both `RootComponents.Add` lines. Add only the Toolkit using and the registration: + +```csharp +using Syncfusion.Blazor.Toolkit; // add + +// ...template: builder.RootComponents.Add("#app"); builder.RootComponents.Add("head::after");... + +builder.Services.AddSyncfusionBlazorToolkit(); // add, before Build() +``` + +### _Imports.razor + +Add the single root namespace. In a split Web App add it to the `_Imports.razor` of **every project that renders Toolkit components** (server `Components/_Imports.razor` and `.Client/_Imports.razor`). + +```razor +@using Syncfusion.Blazor.Toolkit +``` + +Do **not** add domain-specific usings such as `@using Syncfusion.Blazor.Toolkit.Buttons` — those namespaces were removed in 2.0. Components such as `SfButton` resolve from the root `@using Syncfusion.Blazor.Toolkit` alone. + +### Host file and theming + +**Do not** add a Toolkit theme stylesheet link. In 2.0, styling comes from: + +1. **CSS isolation** — component scoped styles from the package. +2. **`SfThemeRoot`** — shared theme layer emitted automatically when a Toolkit component is in the tree (or place an explicit `` if you need theme tokens with no Toolkit component present). + +Keep the template-generated host file intact: `HeadOutlet`, `Routes` and its render-mode directive, `app.css` / `{Project}.styles.css`, and the framework script tag. When upgrading from 1.x, **remove** any `` (or `highcontrast.min.css` / per-component `.min.css`) entries. See [Theme and host files](./references/theme-and-host-files.md). + +## Migrating from Toolkit 1.x to 2.0 + +1. Update the package to 2.0.0 or newer. +2. Replace domain-specific usings for the namespaces that actually moved — `.Buttons`, `.Calendars`, `.Charts`, `.Inputs`, `.Popups`, `.Spinner`, and similar — with the single `@using Syncfusion.Blazor.Toolkit`. **Do not remove `@using Syncfusion.Blazor.Toolkit.Data`** (or fully qualified `.Data.*` references): the 2.0 package still ships `DataAdaptor`, `DataManager`, `Query`, and the `.Data` namespace there. +3. Update fully qualified type names that used the removed child namespaces (`.Buttons`, `.Calendars`, etc.) to the root namespace. Leave any `.Data.*` names alone — those APIs still live under `.Data`. +4. **Remove** any 1.x Toolkit theme `` tags (`fluent.min.css`, `highcontrast.min.css`, per-component stylesheets). Component styles are CSS-isolated; the shared theme is delivered by `SfThemeRoot`. +5. Review custom CSS overrides that targeted unscoped toolkit class names; isolation may require `::deep` or scope adjustments. +6. If subclasses of `DataAdaptor` exist, add `where T : notnull`. +7. Collection return types that were `List` may now be `IList`; avoid casting to `List`. + +## Hybrid / MAUI boundary + +This skill does not cover .NET MAUI Blazor Hybrid. When a user asks, explain the boundary instead of applying Web App steps. Verified against the `maui-blazor` template: + +- There is no `App.razor`, `_Host.cshtml`, `HeadOutlet`, or render mode. The UI runs in a `BlazorWebView` declared in `MainPage.xaml`. +- The host page is `wwwroot/index.html`, with a `
` root wired through ``. It loads `_framework/blazor.webview.js`. +- Services are registered in `MauiProgram.cs`, after `builder.Services.AddMauiBlazorWebView();`. +- The Toolkit's `net10.0` assets resolve for the platform TFMs `net10.0-android`, `net10.0-ios`, `net10.0-maccatalyst` and `net10.0-windows10.0.19041.0` (verified by restore against 2.0.0). `net9.0-android` and `net8.0-android` fail on the SDK itself (`NETSDK1147`, MAUI workload not installed), so Toolkit support there was not testable. Even so, this skill does not configure Hybrid apps: point the user to Hybrid-specific documentation. The same TFM check applies: a MAUI project on an unsupported .NET version needs an upgrade first. + +## Common Mistakes + +| Mistake | Symptom | Fix | +| --- | --- | --- | +| Toolkit installed on .NET 6, .NET 7, or older | NuGet restore fails (`NU1202` / no compatible assets for the TFM) | Upgrade the app to .NET 8 or later first. Never change the TFM just to make the package install | +| `AddSyncfusionBlazorToolkit()` missing on a host that renders Toolkit | HTTP 500: `no registered service of type ...SyncfusionBlazorToolkitService` | Register on every rendering host, including the server for `.Client` components and for static SSR | +| Adding a 1.x Toolkit theme `` (`fluent.min.css` / `highcontrast.min.css`) | Unnecessary; may confuse troubleshooting | Remove it; rely on `SfThemeRoot` + CSS isolation | +| Host file replaced wholesale while adjusting theming | `HeadOutlet`, `Routes`, or the render-mode directive is lost; events stop firing | Restore the template-generated file; do not add Toolkit theme links | +| App `{Project}.styles.css` / `app.css` link removed | App or scoped styles missing | Keep the template stylesheet links | +| `Program.cs` retyped from a trimmed sample | `CS0246` on `App`, and `UseExceptionHandler`, `UseHsts`, `MapStaticAssets` and `app.Run()` are lost | Restore the template file, then add only the `using` and the registration line | +| Template's `AddAdditionalAssemblies(typeof(.Client._Imports).Assembly)` deleted from `MapRazorComponents()` | Routable pages in `.Client` return 404 | Restore the call exactly as the template generated it | +| Commercial package added for a Toolkit-only app | License prompt, missing Toolkit components | Replace that package with `Syncfusion.Blazor.Toolkit`. If other pages still use commercial components, keep those packages and `SyncfusionLicenseProvider.RegisterLicense(...)` | +| Domain-specific `@using` from 1.x still present | `CS0234` or unresolved type; components not recognized | Replace with `@using Syncfusion.Blazor.Toolkit` only | +| Component namespace missing (or still using 1.x child namespace) | Razor warning `RZ10012`; `` renders as an unstyled unknown element that ignores events | Add `@using Syncfusion.Blazor.Toolkit` to `_Imports.razor` of the project that renders it | +| Custom CSS from 1.x no longer applies | Styles ignored after upgrade | Account for CSS isolation; use `::deep` for child selectors when needed | +| Added an external Syncfusion CDN script tag | JavaScript conflicts or duplicate library errors | Remove the CDN script; Toolkit JS ships in the NuGet package | +| Assumed `-int Server` is global, so an interactive Toolkit component has no interactive boundary | Clicks, bindings, dialogs and calendar navigation do nothing | Check `Routes`. In a per-page app put the template `@rendermode` on the page **or** on a wrapper that hosts the control; in a `-ai` app inherit `Routes` | +| `@rendermode` added to standalone WASM or legacy Server | No effect, and it can look like a fix | Remove it; those apps are already interactive | +| Child `@rendermode` differs from the parent interactive mode | Runtime error; a child cannot switch interactive modes | Match the inherited mode, or move the component to a page with the intended mode | +| Auto or WebAssembly endpoint removed from a split Web App | Client components never load, or load only after a server round-trip | Keep the endpoints the template generated | +| `InteractiveWebAssembly` or `InteractiveAuto` page created in the **server** project | HTTP 200 and the component shows from the prerender, then the browser console reports `Root component type '...' could not be found in the assembly ''` and nothing is interactive | Move the page and its components into the `.Client` project | +| `RootComponents.Add("#app")` added to `.Client` | The Client host has no `#app` element | Remove it. That call belongs only in standalone WebAssembly | + +## Top Failure Symptoms + +- **Unstyled components**: missing package/registration/root `@using`; no Toolkit component (and no explicit ``) in the tree; custom overrides need isolation adjustment; or residual 1.x expectations about `fluent.min.css`. See [Theme and host files](./references/theme-and-host-files.md). +- **HTTP 500 mentioning `SyncfusionBlazorToolkitService`**: `AddSyncfusionBlazorToolkit()` is missing on a host that renders Toolkit. See [Troubleshooting guide](./references/troubleshooting.md). +- **Clicks or inputs do nothing**: check for an inherited `Routes` mode first; if none, ensure an interactive boundary (page `@rendermode` or interactive wrapper). See [Render modes explained](./references/render-modes.md). +- **Only one half of a split app works**: register Toolkit on both hosts. See [Split Blazor Web App registration](./references/split-webapp-registration.md). +- **License prompt after installing `Syncfusion.Blazor`**: that is the commercial package. See [Package identity](./references/package-identity.md) before removing anything the app still uses. +- **Unresolved types after upgrading from 1.x**: domain namespaces were removed; use only `@using Syncfusion.Blazor.Toolkit`. + +## Next Steps + +After installation, use the component demos or component-specific guidance for API details; this skill only covers setup and configuration. + +## References + +- [Package identity](./references/package-identity.md) +- [Split Blazor Web App registration](./references/split-webapp-registration.md) +- [Theme and host files](./references/theme-and-host-files.md) +- [Render modes explained](./references/render-modes.md) +- [Troubleshooting guide](./references/troubleshooting.md) diff --git a/plugins/dotnet-blazor/skills/syncfusion-blazor-toolkit-install/references/package-identity.md b/plugins/dotnet-blazor/skills/syncfusion-blazor-toolkit-install/references/package-identity.md new file mode 100644 index 0000000000..7fd4edc922 --- /dev/null +++ b/plugins/dotnet-blazor/skills/syncfusion-blazor-toolkit-install/references/package-identity.md @@ -0,0 +1,49 @@ +# Package Identity Reference + +## Syncfusion.Blazor.Toolkit vs. commercial Syncfusion.Blazor* + +### The open-source Toolkit: Syncfusion.Blazor.Toolkit + +- **NuGet package name**: `Syncfusion.Blazor.Toolkit` (verified at version 2.0.0) +- **License**: MIT +- **Target frameworks**: `net8.0`, `net9.0`, `net10.0` +- **Scope**: Open-source Blazor toolkit for the current published component set +- **Repository**: https://github.com/syncfusion/blazor-toolkit +- **Components included**: Refer to the official Syncfusion Blazor Toolkit documentation for the authoritative and current component list. This skill is not a component reference. +- **No license key required**: Toolkit is free to use without registration +- **Breaking changes in 2.0**: Namespace consolidation (single root `Syncfusion.Blazor.Toolkit`), CSS isolation, and `SfThemeRoot` theme delivery. Host links to `fluent.min.css` / `highcontrast.min.css` are **no longer required**. Not source-compatible with 1.0.2. + +### Commercial Syncfusion.Blazor* Packages + +- **Package name(s)**: `Syncfusion.Blazor`, `Syncfusion.Blazor.Core`, `Syncfusion.Blazor.Buttons`, `Syncfusion.Blazor.Calendars`, `Syncfusion.Blazor.Charts`, `Syncfusion.Blazor.Grids`, `Syncfusion.Blazor.Inputs`, etc. +- **License**: Commercial (requires valid license key for production) +- **Scope**: Full-featured Syncfusion component library +- **Requires**: License registration through `Syncfusion.Licensing.SyncfusionLicenseProvider.RegisterLicense(...)`. There is no `AddSyncfusionLicense()` API. +- **Not the same as Toolkit**: Commercial packages are separate products with different APIs and licensing +- **Do not remove them blindly**: If any page still uses a commercial component, keep that package and its `RegisterLicense` call. Remove them only when Toolkit is replacing every commercial component in the app. + +## Install the Toolkit (and ONLY the Toolkit for this skill) + +```bash +# Correct: Install Toolkit (prefer latest 2.x) +dotnet add package Syncfusion.Blazor.Toolkit + +# Wrong: Do NOT install commercial packages for Toolkit tasks +dotnet add package Syncfusion.Blazor +dotnet add package Syncfusion.Blazor.Core +dotnet add package Syncfusion.Blazor.Buttons +``` + +## Verify Installation + +Check the `.csproj` file: + +```xml + + + + + + + +``` diff --git a/plugins/dotnet-blazor/skills/syncfusion-blazor-toolkit-install/references/render-modes.md b/plugins/dotnet-blazor/skills/syncfusion-blazor-toolkit-install/references/render-modes.md new file mode 100644 index 0000000000..0aa50968a7 --- /dev/null +++ b/plugins/dotnet-blazor/skills/syncfusion-blazor-toolkit-install/references/render-modes.md @@ -0,0 +1,124 @@ +# Render Modes Reference + +Toolkit components need an **interactive boundary** whenever they handle clicks, bindings, dialogs, calendar navigation, or any other client interaction. A Toolkit component with no interactive ancestor is display-only. + +> **Framework support.** `Syncfusion.Blazor.Toolkit` 2.0.0 targets `net8.0`, `net9.0`, and `net10.0`. Always check the project's `` before installation. On `net6.0`, `net7.0`, or older frameworks, NuGet restore fails with an incompatibility such as `NU1202` because the package has no compatible assets for those TFMs. Do not expect a later `CS0246` as the primary signal—fix the framework mismatch first. Do not proceed with Toolkit installation on unsupported frameworks. Recommend upgrading the application to .NET 8 or later first, then continue with the installation steps. + +> **Namespaces (2.0).** All public component types—including `SfButton`—live in the single root namespace `Syncfusion.Blazor.Toolkit`. Domain-specific namespaces from 1.x were removed. Each sample below includes `@using Syncfusion.Blazor.Toolkit`. If it is already in `_Imports.razor`, the per-page line can be dropped. + +Toolkit itself only needs `AddSyncfusionBlazorToolkit()`. Keep every `AddInteractive*` and `AddAdditionalAssemblies(...)` call exactly as the project template generated it; do not add or remove them for Toolkit. + +## Template matrix (verified with `dotnet new blazor`) + +`dotnet new blazor -int ` makes the **server project** interactive-capable but leaves pages **static** until a page (or a child component) opts in. Adding `-ai` (`--all-interactive`) puts the mode on `HeadOutlet` and `Routes` in `App.razor`, so every page inherits it. + +| Template command | Scope | `.Client` project | `Routes` in `App.razor` | Sample page | +| --- | --- | --- | --- | --- | +| `-int None` | Static SSR only | No | `` | none; no interactive endpoints | +| `-int Server` | **Per-page** | No | `` (static) | `Counter.razor` has `@rendermode InteractiveServer` | +| `-int Server -ai` | **Global** | No | `` | pages inherit; no per-page directive | +| `-int WebAssembly` | **Per-page** | Yes | `` (static) | `Counter.razor` has `@rendermode InteractiveWebAssembly` | +| `-int WebAssembly -ai` | **Global** | Yes | `` | pages inherit | +| `-int Auto` | **Per-page** | Yes | `` (static) | `Counter.razor` has `@rendermode InteractiveAuto` | +| `-int Auto -ai` | **Global** | Yes | `` | pages inherit | + +## Static SSR only (`-int None` or a page with no interactive boundary) + +**Toolkit limitation**: Static SSR is not sufficient for interactive Toolkit components. Event handlers and state changes will not work. Toolkit services are still required: a static page that renders `SfButton` returns HTTP 500 without `AddSyncfusionBlazorToolkit()`. + +**Example (display-only)**: +```razor +@page "/status" +@using Syncfusion.Blazor.Toolkit + +Read-only button +``` + +## Interactive Server + +**Per-page (`-int Server`)**: ensure an interactive boundary. Either: + +- add `@rendermode InteractiveServer` on the **page**, or +- keep the page static and wrap the Toolkit control in a **child component** that declares `@rendermode InteractiveServer`. + +```razor +@page "/counter" +@rendermode InteractiveServer +@using Syncfusion.Blazor.Toolkit + +

Count: @count

+Increment + +@code { + private int count = 0; + private void IncrementCount() => count++; +} +``` + +**Global (`-int Server -ai`)**: `Routes` already carries `@rendermode="InteractiveServer"`. Write the same page **without** a page-level `@rendermode` line (and do not put a different mode on a child). + +**`Program.cs`**: leave the template's `AddInteractiveServerComponents()` on `AddRazorComponents()` and `AddInteractiveServerRenderMode()` on `MapRazorComponents()` as generated. Add only `using Syncfusion.Blazor.Toolkit;` and `builder.Services.AddSyncfusionBlazorToolkit();` before `builder.Build()`. Do **not** add WebAssembly services to this template. + +## Interactive WebAssembly (Blazor Web App) + +Interactive pages live in the `.Client` project. Default prerendering still runs the component on the server first, so the server also needs Toolkit services. + +**Per-page (`-int WebAssembly`)**: interactive boundary on the page **or** a wrapper component, both in `.Client`, with `@rendermode InteractiveWebAssembly`. Verified: an `InteractiveWebAssembly` page placed in the server project returns HTTP 200 and shows the button from the prerender, then fails in the browser with `Root component type '...' could not be found in the assembly ''`. + +```razor +@page "/counter" +@rendermode InteractiveWebAssembly +@using Syncfusion.Blazor.Toolkit + +

Count: @count

+Increment + +@code { + private int count = 0; + private void IncrementCount() => count++; +} +``` + +**Global (`-int WebAssembly -ai`)**: `Routes` already carries `@rendermode="InteractiveWebAssembly"`. Omit the page directive. Interactive pages and Toolkit components still live in the **`.Client` project** (the generated template puts `Routes` and pages there); do not put interactive Toolkit pages under the server project. + +**`Program.cs`** (server and `.Client`): the template registers WebAssembly endpoints only. Keep them and `AddAdditionalAssemblies(...)` on `MapRazorComponents()`. Add `using Syncfusion.Blazor.Toolkit;` and `builder.Services.AddSyncfusionBlazorToolkit();` to **both** the server and `.Client/Program.cs`. Do not add `RootComponents.Add("#app")` to `.Client`. See [Split Blazor Web App registration](./split-webapp-registration.md). + +### Standalone WebAssembly (not a Web App) + +Standalone Blazor WebAssembly is a different app (no Web App host, no `.Client` split): it is **already interactive**, has **no** `@rendermode`, and its `Program.cs` already contains `RootComponents.Add("#app")`. Do **not** add `@rendermode InteractiveWebAssembly`. Add only the Toolkit `using` and `AddSyncfusionBlazorToolkit()`. + +## Interactive Auto + +First visit uses server interactivity; later visits use the cached WebAssembly bundle once it has downloaded. A **running** component does **not** switch runtimes mid-session. As with WebAssembly, interactive Auto pages and components must live in the `.Client` project. Verified: an `@rendermode InteractiveAuto` page in the server project prerenders then fails in the browser with `Root component type '...' could not be found in the assembly ''`. See https://learn.microsoft.com/aspnet/core/blazor/components/render-modes + +**Per-page / global**: same boundary rules as WebAssembly, with `@rendermode InteractiveAuto` (or inherited from `Routes` when using `-ai`). Interactive pages and Toolkit components must live in **`.Client`** for both per-page and global Auto. + +**`Program.cs`** (server and `.Client`): the template registers **both** Interactive Server and Interactive WebAssembly, plus `AddAdditionalAssemblies(...)`. Keep all of it. Add the Toolkit `using` and `AddSyncfusionBlazorToolkit()` to **both** hosts. Do not add `RootComponents.Add("#app")` to `.Client`. + +## Decision Tree + +1. **Does the component handle clicks, bindings, dialogs, calendar navigation, or any client interaction?** + - **No** → Static rendering is enough (services are still required). Stop. + - **Yes** → Continue. +2. **Which app is this?** + - **Legacy `_Host.cshtml` Server or standalone WebAssembly** → Already interactive. Do **not** add `@rendermode`. + - **Blazor Web App** → Continue. +3. **Is `Routes` in `App.razor` already carrying `@rendermode`?** + - **Yes (global, `-ai`)** → Inherit it. Do not add a different mode on a child. + - **No (per-page)** → The Toolkit control (and its handlers) must sit inside an **interactive boundary**. Either: + - put `@rendermode InteractiveServer` / `InteractiveWebAssembly` / `InteractiveAuto` (matching the template) on the **page**, or + - keep the page static SSR and wrap the Toolkit control in a **child component** that declares the same `@rendermode` (Blazor allows interactive children on a static page). + +Do **not** leave an interactive Toolkit control with no interactive ancestor. The page itself does not have to be interactive. + +## Common Mistakes + +1. **Assuming `-int Server` is global**: it is per-page. Only `-ai` is global. A page without an interactive boundary is static SSR in a per-page app. +2. **Leaving an interactive Toolkit component outside any interactive boundary**: clicks, bindings, and dialogs do nothing. Use a page `@rendermode` **or** an interactive wrapper so the page can stay static SSR. +3. **Adding `@rendermode` under an inherited mode**: if `Routes` already has one (global), a child that names a different mode fails. Match the parent or move the component. +4. **Treating standalone WebAssembly or legacy Server as needing `@rendermode`**: they have no render modes. +5. **Adding WebAssembly endpoints to a server-only project**: Toolkit does not need them; keep the template shape. +6. **Mixing the WebAssembly and Auto templates**: `-int WebAssembly` registers WebAssembly only; `-int Auto` registers both. Keep what the template generated. +7. **Editing endpoints to "fit" Toolkit**: Toolkit needs only `AddSyncfusionBlazorToolkit()`. Do not add or remove `AddInteractive*` or `AddAdditionalAssemblies(...)`. +8. **Describing Auto as a live runtime switch**: a running component does not migrate mid-session. +9. **Assuming a missing directive means the component is interactive**: read `Routes` in `App.razor` first, then the page or wrapper. diff --git a/plugins/dotnet-blazor/skills/syncfusion-blazor-toolkit-install/references/split-webapp-registration.md b/plugins/dotnet-blazor/skills/syncfusion-blazor-toolkit-install/references/split-webapp-registration.md new file mode 100644 index 0000000000..074543eefc --- /dev/null +++ b/plugins/dotnet-blazor/skills/syncfusion-blazor-toolkit-install/references/split-webapp-registration.md @@ -0,0 +1,76 @@ +# Split Blazor Web App Service Registration + +> **Framework support.** `Syncfusion.Blazor.Toolkit` 2.0.0 targets `net8.0`, `net9.0`, and `net10.0`. Always check the `` of **both** projects before installation. On `net6.0`, `net7.0`, or older frameworks, NuGet restore fails with an incompatibility such as `NU1202` because the package has no compatible assets for those TFMs. Do not expect a later `CS0246` as the primary signal—fix the framework mismatch first. Do not proceed with Toolkit installation on unsupported frameworks. Recommend upgrading the application to .NET 8 or later first, then continue with the installation steps. + +A generated `.Client` project is not a standalone WebAssembly app. The server owns `App.razor`, and the host markup has no `#app` element. Never call `RootComponents.Add("#app")` in `.Client/Program.cs`. + +## Both hosts must register Toolkit + +Default prerendering runs WebAssembly and Auto components on the server first. Verified: with `-int WebAssembly`, registering Toolkit **only** in `.Client` makes a `.Client` page return HTTP 500; adding the server registration returns 200. + +```text +System.InvalidOperationException: Cannot provide a value for property 'SyncfusionService' on type +'Syncfusion.Blazor.Toolkit.SfButton'. There is no registered service of type +'Syncfusion.Blazor.Toolkit.SyncfusionBlazorToolkitService'. +``` + +The error is the same for any host that renders a Toolkit component without the registration, including static SSR pages. Disable prerendering only if the user asks; otherwise register on both hosts. + +## Make only the additions; keep the template + +Each template generates its own endpoint calls. **Do not retype `Program.cs`.** A trimmed copy drops `using .Components;` (`CS0246` on `App`) and loses `UseExceptionHandler`, `UseHsts`, `UseHttpsRedirection`, the static-asset mapping (`MapStaticAssets` on .NET 9+, `UseStaticFiles` on .NET 8) and `app.Run()`. + +| Template | Already generated on the server (leave alone) | +| --- | --- | +| `-int Server` (no `.Client` project) | `AddRazorComponents().AddInteractiveServerComponents()`; `MapRazorComponents().AddInteractiveServerRenderMode()` | +| `-int WebAssembly` | `AddRazorComponents().AddInteractiveWebAssemblyComponents()`; `MapRazorComponents().AddInteractiveWebAssemblyRenderMode().AddAdditionalAssemblies(typeof(.Client._Imports).Assembly)` | +| `-int Auto` | `AddRazorComponents().AddInteractiveServerComponents().AddInteractiveWebAssemblyComponents()`; `MapRazorComponents().AddInteractiveServerRenderMode().AddInteractiveWebAssemblyRenderMode().AddAdditionalAssemblies(typeof(.Client._Imports).Assembly)` | + +`AddAdditionalAssemblies(...)` sits on `MapRazorComponents()`, not on `AddRazorComponents()`, and it is not a Toolkit setting. Never add, remove, or move it for Toolkit. The three setups are different templates; do not mix them. Adding `AddInteractiveServerComponents()` to a WebAssembly template, or removing it from an Auto template, changes the app's render-mode support and is not needed for Toolkit. + +## Server `Program.cs` (all three templates) + +Two additions: + +```csharp +using Syncfusion.Blazor.Toolkit; // add at the top + +// ...template code unchanged... + +builder.Services.AddSyncfusionBlazorToolkit(); // add before builder.Build() + +var app = builder.Build(); +``` + +## `.Client/Program.cs` (`-int WebAssembly` and `-int Auto` only) + +The template already has `using Microsoft.AspNetCore.Components.WebAssembly.Hosting;`. Two additions: + +```csharp +using Microsoft.AspNetCore.Components.WebAssembly.Hosting; // already generated +using Syncfusion.Blazor.Toolkit; // add + +var builder = WebAssemblyHostBuilder.CreateDefault(args); + +builder.Services.AddSyncfusionBlazorToolkit(); // add + +await builder.Build().RunAsync(); +``` + +## Interactive Auto behavior + +The first visit runs on the server; later visits use the cached WebAssembly bundle. A running component does not switch runtimes. Both hosts therefore need the registration. + +## Common Mistake: Registering only one host + +**Symptom**: HTTP 500 with the `SyncfusionBlazorToolkitService` error above, either on first load (server missing) or when a `.Client` component runs in the browser (client missing). + +**Fix**: Register on every host that renders it, keep the template's endpoints, and never add `RootComponents.Add("#app")` to `.Client`. + +## Component namespaces in both projects + +Add the single root namespace `@using Syncfusion.Blazor.Toolkit` to the `_Imports.razor` of every project that renders Toolkit components. Domain-specific namespaces from Toolkit 1.x (for example `Syncfusion.Blazor.Toolkit.Buttons`) were removed in 2.0. A missing root namespace only warns (`RZ10012`) and renders an unstyled unknown element. + +## Theming in a Split Web App + +Do **not** add a Toolkit theme stylesheet link. From 2.0, `SfThemeRoot` emits the shared theme layer when Toolkit components render, and component styles use CSS isolation. Keep the template's own stylesheet links in `Components/App.razor` (`app.css`, `{Project}.styles.css`, etc.). When migrating from 1.x, remove any `_content/Syncfusion.Blazor.Toolkit/styles/*.css` links. diff --git a/plugins/dotnet-blazor/skills/syncfusion-blazor-toolkit-install/references/theme-and-host-files.md b/plugins/dotnet-blazor/skills/syncfusion-blazor-toolkit-install/references/theme-and-host-files.md new file mode 100644 index 0000000000..1c8a3d3786 --- /dev/null +++ b/plugins/dotnet-blazor/skills/syncfusion-blazor-toolkit-install/references/theme-and-host-files.md @@ -0,0 +1,50 @@ +# Theme and Host Files Reference + +From Toolkit **2.0**, theming no longer requires linking `fluent.min.css` or `highcontrast.min.css` in the host file. Component styles use Blazor CSS isolation; the shared theme layer is emitted at render time by `SfThemeRoot`. + +> **Framework support.** `Syncfusion.Blazor.Toolkit` 2.0.0 targets `net8.0`, `net9.0`, and `net10.0`. Always check the project's `` before installation. On `net6.0`, `net7.0`, or older frameworks, NuGet restore fails with an incompatibility such as `NU1202` because the package has no compatible assets for those TFMs. Do not expect a later `CS0246` as the primary signal—fix the framework mismatch first. Do not proceed with Toolkit installation on unsupported frameworks. Recommend upgrading the application to .NET 8 or later first, then continue with the installation steps. + +> **Do not replace the host file.** Keep `HeadOutlet`, `Routes`, the render-mode directive on `Routes`, the app's own styles link (`app.css` / `{Project}.styles.css`), and the framework script tags exactly as the template generated them. + +## Theme delivery model (2.0) + +Two tiers — neither requires a Toolkit theme `` in the host: + +1. **Shared theme layer (`SfThemeRoot`)** + Writes a single `