Repository navigation
feat(avalonia): Phase 2 foundation and P0 components - #7
Merged
Merged
Conversation
added 9 commits
October 7, 2026 12:49
…toggle examples/Avalonia.Demo (Avalonia 12.1.3, .NET 10) is where Avalonia components are developed, as MAUI.Demo is for MAUI. Its root namespace is AvaloniaDemo so it doesn't sit inside Avalonia's, and implicit usings are off as in 'dotnet new avalonia.app', so a component missing a using fails in the demo instead of in a user's app. shell keeps the MAUI token names, palettes and radii and publishes both palettes as theme dictionaries, so a theme switch repaints without re-publishing; Token() binds a property to a resource. icon draws the same 110 Lucide icons with a custom Render and picks the icon with Kind, since every Avalonia control already has a Name. generate-icons.py now writes both Icon.cs files from the same icon list.
…ggle sync-templates.py also copies examples/Avalonia.Demo into each template's [NativePlatform.Avalonia] entry. Dependencies still come from the MAUI file; the script fails if an Avalonia file uses one the template doesn't declare. Tests check every Avalonia template for the namespace placeholder, no MAUI types, no hard-coded colors, and Avalonia content in all of its dependencies, so an Avalonia install never pulls in MAUI-only code.
In an Avalonia project init prints where to call ShellTheme.EnsureInitialized and the XAML namespace, instead of the MAUI steps. list shows only components with a template for the project's platform, so Avalonia projects don't see MAUI-only components as available.
ARCHITECTURE describes the pattern in use (one C# file per component built in code, no .axaml) instead of the planned TemplatedControl one. DEVELOPMENT_PLAN records the foundation, the remaining P0/P1 work and the move to the ShellIcons packages once they are published.
Projects from 'dotnet new avalonia.app' don't set <RootNamespace>, so the CLI used the project name, and 'my-app' produced 'namespace my-app.Components.UI', which doesn't compile. Without the property the namespace is now the project name made safe the way 'dotnet new' does it: invalid characters become '_' and a leading digit gets a '_' prefix ('my-app' → 'my_app', '2fa.app' → '_2fa.app').
Token() bound a resource observable and dropped the subscription. A later Token() on the same property added a second binding, and ClearValue/SetValue didn't remove the first, so on the next theme change the stale binding repainted the property: Ghost and Link buttons and the Outline badge turned dark after switching to light. Token() now keeps one binding per control and property and disposes the previous one; ClearToken() removes it before a plain value is set.
button (+ button-variants), input, label, checkbox, switch, card with header/content/footer, separator, badge, progress and alert, with the MAUI names, properties, variants and 40px sizing. Avalonia-specific choices: - shell gains ShellFocus.Ring (shadcn's ring-2 ring-offset-2, keyboard focus only, replacing Fluent's focus adorner) and token colors at an opacity for glows and shadows. - input clears the Fluent TextBox chrome by overriding its TextControl* resources, so its own Border is the only frame. - card is a Border whose XAML children go to Items, because Panel.Render is sealed and Border takes a single child. - The button spinner advances on a frame timer; an Animation on the RotateTransform throws (the transform animator expects the control) and on the control it didn't turn. sync-templates.py walks subfolders for Avalonia too (Variants/ButtonVariants.cs). The two registry tests that used button as a MAUI-only example now use WinUI and the button's two platforms. Checked: every P0 component installs alone into a fresh 'dotnet new avalonia.app' and builds with 0 warnings; all of them in one 'my-app' build and render; the demo in light and dark, with the focus ring and the loading state.
COMPONENTS gains an Avalonia section: what is ported, setup after init, and the differences (Icon Kind, MaxLength 0 means no limit, Card.Items, HorizontalAlignment, keyboard-only focus ring).
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
First Avalonia slice of ShellUI Native (Phase 2): the groundwork plus the P0 components, built the same way as MAUI (one C# file per component, developed in a demo app, copied into the CLI templates).
Foundation
examples/Avalonia.Demo(Avalonia 12.1.3, .NET 10, implicit usings off as indotnet new avalonia.app), in the solution and in CI on Linux, Windows and macOSshell: same theme tokens, palettes and radii as MAUI; both palettes published as theme dictionaries so a theme switch repaints without re-publishing;Token()binds a property to a token,ShellFocus.Ringdraws shadcn's keyboard-only focus ringicon: the same 110 Lucide icons, picked withKind(every Avalonia control already has aName);theme-togglegenerate-icons.pywrites bothIcon.csfiles;sync-templates.pywrites the[NativePlatform.Avalonia]template entries and fails if an Avalonia file uses a dependency the template doesn't declareP0 components
ShellLabel), checkbox, switch, card + header/content/footer, separator, badge, progress, alert, with the MAUI names, properties, variants and 40px sizingItemsCLI
initin an Avalonia project prints the Avalonia setup steps;listshows only components with a template for the project's platform<RootNamespace>get a valid namespace from the project name (my-app→my_app), asdotnet newdoesFixes found while testing
Verification
dotnet build ShellUI.Native.slnx: 0 warnings; tests 585/585; each commit builds the Avalonia demo and passes the testsdotnet new avalonia.appand builds with 0 warnings; all of them together inmy-appbuild and renderAvalonia templates are not on NuGet yet; they ship with the next release.