Add Reactor (Microsoft.UI.Reactor) dotnet new templates - #6620
Open
Alexandre Zollinger Chohfi (azchohfi) wants to merge 34 commits into
Open
Add Reactor (Microsoft.UI.Reactor) dotnet new templates#6620Alexandre Zollinger Chohfi (azchohfi) wants to merge 34 commits into
Alexandre Zollinger Chohfi (azchohfi) wants to merge 34 commits into
Conversation
Adds four Reactor project templates to the Microsoft.WindowsAppSDK.WinUI.CSharp.Templates dotnet-new pack, mirroring the WinUI templates but for Microsoft.UI.Reactor (pure C#, no XAML): - Reactor Blank App (reactor, reactor-blank) - Reactor MVU App (reactor-mvu) - Reactor NavigationView (reactor-navview) - Reactor TabView App (reactor-tabview) Wired into dev/Templates/templates.props via the DotnetNewOnlyProjectTemplate slot (dotnet-new only, no VSIX, no manifest; Reactor apps run unpackaged). Each shares a common csproj referencing Microsoft.UI.Reactor + Microsoft.WindowsAppSDK, bundles the WinAppSDK runtime self-contained, and enables the Debug-only Reactor devtools surface. README and Test-DotnetNewTemplates.ps1 updated to document and validate the new templates. Validated end-to-end: pack -> install -> dotnet new -> build (Debug + Release) for all four templates. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
TitleBar(...).Icon(FontIcon(...)) threw System.ArgumentException (E_INVALIDARG) at runtime when Reactor set TitleBar.IconSource on Windows App SDK 2.1.3, so the scaffolded Blank, MVU, and TabView apps crashed on launch. The glyph was only a placeholder, so drop the icon; the title bar still shows the title text and all four templates now launch cleanly (validated with dotnet run). Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
microsoft/microsoft-ui-reactor#855 fixes the IconResolver FontSize=NaN crash (FontIcon in an IconSource slot without an explicit size threw ArgumentException from TitleBar.set_IconSource). That fix ships in Microsoft.UI.Reactor 0.1.0-preview.12, so restore the placeholder title-bar app-mark icon in the Blank, MVU, and TabView templates and bump the default reactorVersion 0.1.0-preview.11 -> 0.1.0-preview.12 across all four templates. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
|
Azure Pipelines: There may be pipelines that require an authorized user to comment /azp run to run. |
Alexandre Zollinger Chohfi (azchohfi)
marked this pull request as ready for review
July 15, 2026 05:01
|
Azure Pipelines: There may be pipelines that require an authorized user to comment /azp run to run. |
Beth Pan (beth-panx)
requested review from
Dinah Xiaoman G (DinahK-2SO) and
Scott Jones (Scottj1s)
July 23, 2026 20:46
Author
|
/azp run |
|
Azure Pipelines: Successfully started running 2 pipeline(s). 1 pipeline(s) were filtered out due to trigger conditions. |
The template smoke-test stage installed only .NET SDK 8.0.x, so scaffolding and building the Reactor templates failed with NETSDK1045 (Reactor targets net10.0 and declares a [10.0,) sdk-version constraint). The WinUI templates auto-detect their TFM from the active SDK, so they built net8.0 and passed, masking the gap. Add a second UseDotNet@2 step (param reactorDotnetSdkVersion, default 10.0.x) to the shared Test-Stage template so the agent has the .NET 10 SDK. Verified locally that the WinUI templates still build cleanly on the .NET 10 SDK, so existing coverage is unaffected. Both the official and PR pipelines consume this shared stage. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Author
|
/azp run |
|
Azure Pipelines: Successfully started running 2 pipeline(s). 1 pipeline(s) were filtered out due to trigger conditions. |
Dinah Xiaoman G (DinahK-2SO)
requested changes
Jul 24, 2026
Dinah Xiaoman G (DinahK-2SO)
requested changes
Jul 24, 2026
Dinah Xiaoman G (DinahK-2SO)
requested changes
Jul 24, 2026
Dinah Xiaoman G (DinahK-2SO)
requested changes
Jul 24, 2026
Review feedback from @DinahK-2SO on #6620: - Remove the explanatory comment block from the Reactor launchSettings.json files (the content overlapped the package README). - Give the MVU, NavigationView, and TabView templates their own icon.png (reusing the existing WinUI mvvm/navigation/tabview template icons) instead of all reusing the blank-app icon. The packaging/taskbar-icon, tabs-in-title-bar, and winui-* short-name comments are still open pending a check with the Reactor team. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Review feedback from @DinahK-2SO on #6620: give each Reactor template a winui-reactor* alias (winui-reactor, winui-reactor-mvu, winui-reactor-navview, winui-reactor-tabview) so they also surface under 'dotnet new list winui' alongside the other WinUI templates. README updated to note the aliases. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Review feedback from @DinahK-2SO on #6620: instead of stacking a separate TitleBar row above the TabView, put the tabs up in the title bar (Edge/Terminal style) to look cleaner and save vertical space. Uses supported Reactor APIs: UseWindow().NativeWindow with ExtendsContentIntoTitleBar + SetTitleBar, the TabView TabStripHeader (app name at the leading edge) and TabStripFooter (draggable region), and UseDpi + UseWindowSize to reserve the caption-button inset (RightInset) across DPI and resize. Verified by scaffolding the template, building, running, and screenshotting the window: the tabs render inline in the title bar with the caption buttons clear. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Per review direction, the four Reactor templates now:
1. Are single-project MSIX packaged (like the WinUI templates) instead of
unpackaged. Each gains app.manifest, Package.appxmanifest (EntryPoint
Windows.FullTrustApplication since Reactor has no XAML App class), the shared
Assets, and PublishProfiles. The csproj switches to EnableMsixTooling +
Microsoft.Windows.SDK.BuildTools + Microsoft.Windows.SDK.BuildTools.WinApp so
'dotnet run' registers a loose package and launches with MSIX identity.
templates.props sets RenameManifestFrom and the template.json files gain the
publisher / guid / build-tools-version symbols and the \\$
modifier.
2. Visually match their WinUI counterparts:
- reactor -> title bar (app icon) + empty content (blank canvas).
- reactor-mvu -> centered 'Hello, WinUI!' + [+]/[-] icon counter (keeps the
UseReducer MVU pattern under the same UI).
- reactor-navview -> title bar + NavigationView Home/About + built-in Settings;
pages render 'Title' + 'This is the X page'.
- reactor-tabview -> MicaAlt, app-icon TabStripHeader, closable Home/About tabs
with a '+' add button, tabs in the title bar.
Validated end-to-end for all four: pack -> install -> scaffold -> build ->
dotnet run (launches packaged with identity) -> screenshot matches the WinUI
counterpart. README updated (templates are now packaged).
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
…font parity - MVU greeting is now 'Hello, Reactor!' (was 'Hello, WinUI!'). - Switch the Reactor text from Heading()/.SemiBold() (raw 28px Bold-700) to the type-ramp factories Title()/BodyStrong()/Body(), which apply the actual WinUI styles (TitleTextBlockStyle 28px Semibold-600, BodyStrongTextBlockStyle, BodyTextBlockStyle). This makes the Reactor headings/body render with the same weight and Segoe UI Variable optical size as the WinUI templates instead of a heavier bold. Applied to the mvu, navview, and tabview page text. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
The Reactor templates hardcoded `Segoe Fluent Icons` on their FontIcons and left the size at WinUI's default. The XAML templates do neither: they use `<FontIcon Glyph="..." />` with no FontFamily, inheriting SymbolThemeFontFamily, which resolves the right icon font for the OS — worth keeping given the templates support Windows 10 1809 and Segoe Fluent Icons is Windows 11 era. The MVVM template also sets FontSize="14" on its counter icons, which ours missed, so the buttons rendered larger than their XAML counterpart: XAML MVVM 58x41 Reactor MVU 67x51 -> 58x42 Verified against Microsoft.UI.Reactor 0.1.0-preview.12: both templates build warning-free and the glyphs render correctly (Icon(FontIcon(...)) resolves through IconResolver, not the Button(string) content path). Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 16d7d2fc-3d7c-41e8-9999-0c2084ba9ea1
Reactor preview.13 adds declarative APIs that let the Navigation and TabView templates drop their imperative escape hatches: - NavigationView: use IsBackButtonVisible / IsPaneToggleButtonVisible and .IsPaneOpen(value, handler) instead of UseRef + OnMount downcast, and select the built-in Settings item via NavigationViewElement.SettingsTag. OnSelectedTagChanged still reports null for Settings by design, so TagToRoute keeps handling both SettingsTag and null. - TitleBar: use .Tall() instead of the UseEffect + DispatcherQueue hop and the redundant .Height(48). - TabView: set FillContentArea, removing the MinHeight workaround. Also bump the reactorVersion default to 0.1.0-preview.13 in all four Reactor template.json files. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 38f0823a-2ee4-4c65-8f3f-7dde6a049509
Drop the hardcoded 1000x700 from all four Reactor templates. Reactor PR #924 makes ReactorApp.Run's width/height optional, so omitting them lets the OS pick the size, matching the XAML templates which set no size at all. Verified identical to a freshly scaffolded XAML app. This requires 0.1.0-preview.13; before #924, omitting width/height meant a hardcoded 1024x768 rather than an OS-chosen size. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 38f0823a-2ee4-4c65-8f3f-7dde6a049509
Author
|
Updated for Microsoft.UI.Reactor 0.1.0-preview.13, which shipped today. preview.13 adds declarative APIs for the things these templates previously had to reach around, so the Navigation and TabView templates lose their imperative escape hatches:
The navigation template is now fully declarative — no Validated against the real package from nuget.org (no local feed, no version override):
The four upstream issues these templates surfaced are all fixed and released: microsoft/microsoft-ui-reactor#914, #915, #916, #917. |
Author
|
/azp run |
|
Azure Pipelines: Successfully started running 2 pipeline(s). 1 pipeline(s) were filtered out due to trigger conditions. |
The Reactor templates were originally unpackaged and their launchSettings.json only declared `commandName: Project` profiles. Making them single-project MSIX updated the csproj and added Package.appxmanifest but left launchSettings behind, so F5 from Visual Studio failed: ...launchSettings.json does not contain a profile with commandName 'MsixPackage'. To debug a packaged single-project MSIX solution, a profile with command name MsixPackage in launchSettings.json is required. `dotnet run` goes through Microsoft.Windows.SDK.BuildTools.WinApp instead, so it worked throughout and the gap went unnoticed. Declare the same Package / Unpackaged pair the WinUI XAML templates ship, with Package first so it is the F5 default, and keep the Reactor devtools profile alongside them. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 16d7d2fc-3d7c-41e8-9999-0c2084ba9ea1
The Reactor templates pinned Microsoft.WindowsAppSDK to 2.1.3 while the WinUI XAML templates default to `*`. That pinned new projects to an older SDK than the one Visual Studio offers everywhere else — 2.3.1 is current, so scaffolded Reactor apps were two releases behind for no reason. 2.1.3 was the version Reactor happened to be built against, not a hard floor: Microsoft.UI.Reactor 0.1.0-preview.13 depends on Microsoft.WindowsAppSDK.WinUI >= 2.1.0. Keep the requirement in the parameter description rather than encoding it as the pin, matching the WinUI templates. Verified with the floated default: all four templates resolve Microsoft.WindowsAppSDK 2.3.1, build warning-free, and launch with package identity. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 16d7d2fc-3d7c-41e8-9999-0c2084ba9ea1
Author
|
/azp run |
|
Azure Pipelines: Successfully started running 2 pipeline(s). 1 pipeline(s) were filtered out due to trigger conditions. |
The dotnet-new template test stage previously installed only the .NET 8 SDK.
Adding the .NET 10 SDK (needed because the Reactor templates target net10.0)
means the muxer now selects 10.0.400 for the pre-existing winui negative
tests as well, which changes the diagnostic NuGet emits for an unparseable
package version:
SDK 8.0.424 / 9.0.317 : no error code; "'not-a-version' is not a valid
version string."
SDK 10.0.400 : MSB4181 - RestoreTask returns false without
logging the descriptive error, so no NU code
surfaces at all.
The old assertion short-circuited on any error code being present and
demanded NU1105, so MSB4181 failed the run. (NU1105 never actually
surfaced on any tested SDK; the test passed via the descriptive-message
fallback.) Accept NU1105/MSB4181 or the descriptive message, and stop a
code's presence from bypassing the fallback.
Verified on 8.0.424 / 9.0.317 / 10.0.400. Unrelated failures (NU1101,
NU1301) still fail the assertion, so it is not weakened to "any failure".
Scenario 5's build check (NETSDK1004), scenario 6 (NU1102) and scenario 7
(NU1301) were confirmed unchanged on SDK 10.
Also corrects an adjacent comment that said NETSDK1005 where the check and
the observed behaviour are both NETSDK1004.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 16d7d2fc-3d7c-41e8-9999-0c2084ba9ea1
Author
|
/azp run |
|
Azure Pipelines: Successfully started running 2 pipeline(s). 1 pipeline(s) were filtered out due to trigger conditions. |
Every other UseDotNet@2 task in this repo pins an exact SDK (6.0.414, 6.0.427, 8.0.100, 9.0.200, 10.0.111); #6624 added the BuildVSIX pin so Component Governance scans a patched toolchain, and #6699 bumped it deliberately for a security release. reactorDotnetSdkVersion was the only new floating pin. Floating is what broke CI: '10.0.x' resolved to 10.0.302 when the task was added on 2026-07-23, then silently jumped a whole feature band when 10.0.400 shipped on 2026-08-11. 10.0.400 changed the NuGet diagnostic for an unparseable package version, so the pre-existing winui invalid-version smoke test started failing with no corresponding source change. Pinned to 10.0.400 rather than the 10.0.111 used by BuildVSIX. The Reactor templates cannot use the 1xx servicing band: Microsoft.UI.Reactor's analyzers and source generators (Reactor.Analyzers, Reactor.Wrappers.Generator, Reactor.Localization.Generator) reference Roslyn 5.6.0.0, and 10.0.111 ships Roslyn 5.0.0.0, so all three are silently disabled with CS9057 while the build still reports success. Verified by building the same scaffolded project on both SDKs: 10.0.111 -> 3x CS9057, 10.0.400 (Roslyn 5.9.0.0) -> 0 warnings. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 16d7d2fc-3d7c-41e8-9999-0c2084ba9ea1
Author
|
/azp run |
|
Azure Pipelines: Successfully started running 2 pipeline(s). 1 pipeline(s) were filtered out due to trigger conditions. |
Follow-up to 5ff625e, which fixed the restore assertion in the same scenario. The build assertion immediately after it failed for the same underlying reason. On .NET SDK 10 NuGet's RestoreTask fails (MSB4181) but still writes a partial obj/project.assets.json. The subsequent --no-restore build therefore reports NETSDK1005 (assets file has no target for the project's TFM) rather than NETSDK1004 (assets file missing). Accept either, since both mean restore did not produce usable assets. Scenario 7's list gains NETSDK1005 for the same reason; it currently resolves to NU1301, but NETSDK1004 is in that list for the 'restore never succeeded' case whose SDK 10 equivalent is 1005. This also reverts the NETSDK1005 -> NETSDK1004 comment change from 5ff625e. That comment was correct as written; I changed it based on a repro that used a bare net8.0 project with no obj directory, which produces NETSDK1004 and does not reproduce the real template's behaviour. Re-verified with a faithful repro (net10.0-windows10.0.26100.0, WinUI props, same build flags), which reproduces CI exactly: assets file present after the failed restore, build fails with NETSDK1005. All four error-code assertions in this script are now backed by faithful repros on the pinned SDK 10.0.400: restore MSB4181, build NETSDK1005, scenario 6 NU1102, scenario 7 NU1301. Unrelated failures still throw. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 16d7d2fc-3d7c-41e8-9999-0c2084ba9ea1
Author
|
/azp run |
|
Azure Pipelines: Successfully started running 2 pipeline(s). 1 pipeline(s) were filtered out due to trigger conditions. |
Author
|
/azp run |
|
Azure Pipelines: Successfully started running 2 pipeline(s). 1 pipeline(s) were filtered out due to trigger conditions. |
Alexandre Zollinger Chohfi (azchohfi)
enabled auto-merge (squash)
August 25, 2026 22:14
Contributor
|
LGTM |
Dinah Xiaoman G (DinahK-2SO)
approved these changes
Aug 27, 2026
Alexandre Zollinger Chohfi (azchohfi)
added a commit
to azchohfi/microsoft-ui-reactor
that referenced
this pull request
Aug 27, 2026
Review follow-up. The packaging-neutral rewrite named `EnableMsixTooling` as the packaged marker and told the agent never to set `WindowsPackageType`. Both were wrong in ways that matter: - `EnableMsixTooling` only enables the single-project MSIX tooling. A project with `WindowsPackageType=None` *and* `EnableMsixTooling=true` builds unpackaged -- `None` wins. Verified live: that combination emits no `AppxManifest.xml` / `resources.pri` / `.build.appxrecipe`, while the same csproj with the property absent emits all three. - Packaged does not require `WindowsPackageType=MSIX`. Omitting the property entirely also yields a packaged app off the default, which is what the templates in microsoft/WindowsAppSDK#6620 do. Mandating `MSIX` would have described that scaffold as broken. - "Don't set `WindowsPackageType` yourself" contradicted `docs/guide/packaging.md`, which tells you to set it to `MSIX` -- and this skill routes readers to that guide two paragraphs later. Both shapes are now described with the property precedence stated, and the rule is scoped to the actual hazard (don't flip the mode of a project you didn't scaffold) rather than to the property. `Package.appxmanifest` stays the discriminator; it is true today and after #6620, so neither change waits on the other. Also drops `app.manifest` as a packaged marker -- the repo's only one belongs to an unpackaged project (`tests/startup_perf/BlankWinUI3`) -- and the present-tense claim about a packaged template's file list. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 784c77a5-bfd2-40f4-96a5-ce447df7c3e2
Alexandre Zollinger Chohfi (azchohfi)
added a commit
to azchohfi/microsoft-ui-reactor
that referenced
this pull request
Aug 27, 2026
Companion to the packaging fix in 525efc2, same defect class: a property of `dotnet new reactorapp` stated as a property of Reactor. The skill claimed the `.csproj` does **not** enable implicit usings. That is true of the shipped template, which sets no `ImplicitUsings` property, and false of the templates in microsoft/WindowsAppSDK#6620 -- `ReactorBlankApp/ProjectTemplate.csproj` sets `<ImplicitUsings>enable</ImplicitUsings>`. The divergence is observable in the scaffolded source: #6620's `App.cs` opens with six usings and no `using System;`, against the seven in `tools/Templates/templates/WinUIApp-CSharp/App.cs:1-7`, which leads with it. That also made the sentence's own worked example misfire, since `System.Linq` is in the implicit set -- an agent told to add `using System.Linq;` before `.Select(...)` finds it already in scope. Reworded so it holds for both: `App.cs` keeps its `using` block and that is still where you add namespaces, with a note that some templates enable implicit usings. The "seven-line using block" count in "Starting a new app" goes with it, for the same reason. The *Required imports* list is left as-is -- spelling `using System;` out explicitly is redundant under implicit usings, not wrong. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 784c77a5-bfd2-40f4-96a5-ce447df7c3e2
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds four Reactor (
Microsoft.UI.Reactor) project templates to the existingMicrosoft.WindowsAppSDK.WinUI.CSharp.Templatesdotnet newpack, mirroring the WinUI templates from #6407 but for Reactor's declarative, pure-C# (no XAML) model.reactor,reactor-blankreactor-mvuUseReducerreactor-navviewNavigationViewshell with multiple pagesreactor-tabviewTabViewshell with multiple tabsWhat changed
dev/Templates/templates.props— four new rows in theDotnetNewOnlyProjectTemplateslot (dotnet-new only, no VSIX). Reactor apps run unpackaged, so there is noPackage.appxmanifest(RenameManifestFromleft unset). This reuses the repo's existing single-source-of-truth pack pipeline.dev/Templates/Source/ProjectTemplates/Desktop/CSharp/Reactor*— the app sources: a sharedProjectTemplate.csproj(referencesMicrosoft.UI.Reactor+Microsoft.WindowsAppSDK,WindowsAppSDKSelfContained, Debug-only Reactor devtools), a single-fileApp.csper pattern, andProperties/launchSettings.json(default + Devtools F5 profiles).dev/Templates/Dotnet/templates/reactor-*— the.template.configfor each (template.json,dotnetcli.host.json,ide.host.json,icon.png). Defaults: Reactor0.1.0-preview.12, Windows App SDK2.1.3,net10.0; overridable via--reactor-version/--wasdk-version.dev/Templates/Dotnet/README.md— documents the new Reactor templates.dev/Templates/Dotnet/Test-DotnetNewTemplates.ps1— adds the four to the scaffold/build validation loop.Validation
Validated end-to-end against the live
Microsoft.UI.Reactor 0.1.0-preview.12:dotnet pack→dotnet new install→ all four register →dotnet new→dotnet build(Debug + Release) →dotnet run. All four launch cleanly, including the title-bar app-mark icon (which relies on theIconResolverfix from microsoft/microsoft-ui-reactor#855, shipped in preview.12).A Microsoft employee must use
/azp runto validate using the PR pipelines.