A UI components library for Avalonia 11.3.x that provides controls, dialogs, behaviors, and helpers for desktop, mobile, and browser applications. Built with ReactiveUI, a strong functional-reactive orientation (Result<T>, Maybe<T>, IObservable<T>), and absolute respect for the MVVM pattern — no logic in views, no UI in ViewModels.
The fastest way to start a new cross-platform Avalonia app on top of Zafiro is the dotnet new template:
dotnet new install Zafiro.Avalonia.Templates
dotnet new zafiro-shell -n MyApp
cd MyApp && dotnet run --project MyApp.DesktopYou get a multi-project solution (Desktop + Browser + Android + iOS) with the Zafiro Shell, [Section] auto-discovery, ReactiveUI, compiled bindings and Zafiro.Avalonia.Mcp.AppHost wired in. See templates/Zafiro.Avalonia.Templates/README.md for details.
dotnet add package Zafiro.AvaloniaFor dialogs:
dotnet add package Zafiro.Avalonia.DialogsFor auto-generated view locators and section registrations (recommended):
dotnet add package Zafiro.Avalonia.GeneratorsWire up your app in one line — works on Desktop, Mobile, and Browser:
public override void OnFrameworkInitializationCompleted()
{
this.Connect(() => new MainView(), view => CompositionRoot.Create(view), () => new MainWindow());
base.OnFrameworkInitializationCompleted();
}Connect handles IClassicDesktopStyleApplicationLifetime and ISingleViewApplicationLifetime automatically, so the same code runs everywhere.
A section-based navigation system integrated with Microsoft.Extensions.DependencyInjection:
ServiceCollection services = new();
services.AddSingleton<IShell, Shell>();
services.AddSingleton(DialogService.Create());
services.AddScoped<INavigator>(provider => new Navigator(provider, logger, RxApp.MainThreadScheduler));
services.AddAllSectionsFromAttributes(logger); // auto-discovers [Section] ViewModels
services.AddTransient<MainViewModel>();
var serviceProvider = services.BuildServiceProvider();
return serviceProvider.GetRequiredService<MainViewModel>();Combined with Zafiro.Avalonia.Generators, sections are discovered from [Section] attributes and registered automatically.
Dialogs that work on both desktop and mobile:
Result<Maybe<T>> result = await dialog.ShowAndGetResult(viewModel, "Title");Dialogs.desktop.mp4
Build multi-step wizards declaratively with SlimWizard:
var wizard = WizardBuilder
.StartWith(() => new Page1ViewModel(), "Step 1")
.NextWith(model => model.Continue.Enhance("Next"))
.Then(result => new Page2ViewModel(result), "Step 2")
.NextWhenValid((vm, prev) => Result.Success(vm.Text!))
.WithCompletionFinalStep();Wizard.mp4
Wraps ReactiveCommand with UX metadata (text, icon, name) and busy state — distinguishing between busy (executing) and disabled (can't execute) via IEnhancedCommand:
var command = ReactiveCommand.CreateFromTask(() => DoSomething());
var enhanced = command.Enhance("Save", name: "save");
// enhanced.IsBusy tracks execution; enhanced.CanExecute tracks enablementAutomatically resolves Views for ViewModels by naming convention (MainViewModel → MainView) and by x:DataType discovery via source generators:
DataTemplates.Add(new NamingConventionViewLocator());With Zafiro.Avalonia.Generators, x:DataType declarations in .axaml files are discovered at compile time and registered automatically.
- Shell / ShellView — Section-based application shell with sidebar navigation.
- Navigator — Observable navigation stack integrated with DI.
- SectionStrip — Tab-like section navigation with grouping support.
- Sections auto-registration — Source generator discovers
[Section]ViewModels and wires DI.
| Control | Description |
|---|---|
| HeaderedContainer | Content with header, footer, and configurable spacing |
| EdgePanel | Panel with Start, Content, and End regions |
| EnhancedButton | Button with icon, role-based theming, and box shadow |
| Loading | Loading indicator with content transition |
| BalancedWrapGrid | Wrap panel with balanced column widths and MaxItemWidth |
| MasterDetailsView | Side list with detail panel, responsive layout |
| ResponsivePresenter | Width-based content swap (Narrow/Wide + Breakpoint) |
| StepIndicator | Visual step progress for wizards |
StringEditorControl.mp4
- DialogService — Show dialogs from ViewModels without coupling to the View layer.
- NotificationService — Push notifications from ViewModels.
- ILauncherService — Open URLs and files from ViewModels.
- EnhancedCommand —
ReactiveCommandwrapper with text/icon metadata, busy/disabled distinction viaIEnhancedCommand. - ReactiveSelection — Observable selection model with multi-select support.
- CommandPool / EnqueueCommandAction — Throttled, pooled command execution.
Connect— One-line app bootstrap for all platforms (Desktop, Mobile, Browser).- NamingConventionViewLocator + DataTypeViewLocator — Convention and
x:DataTypebased ViewModel → View resolution. - IconExtension — Unified icon markup extension supporting Optris and SVG providers.
- ReturnExtension — Markup extension for returning observables in design-time data.
The solution includes runnable samples that demonstrate all features:
# Desktop
dotnet run --project samples/TestApp/TestApp.Desktop
# Browser (WASM)
dotnet run --project samples/TestApp/TestApp.Browser- Functional + Reactive —
Result<T>,Maybe<T>, andIObservable<T>throughout. No exceptions for control flow, explicit error handling everywhere. - MVVM purist — Strict separation: no UI logic in ViewModels, no business logic in Views. Services are injected, never resolved from Views.
- Composition over inheritance — Small, composable building blocks and extension methods.
- ReactiveUI-first — State as observables, commands for intents, no imperative event handlers.
- Cross-platform — Desktop, Android, iOS, and Browser from the same codebase.
Zafiro.Avalonia is an independent community project and is not affiliated with, endorsed by, or sponsored by AvaloniaUI OÜ.
Avalonia is a trademark of AvaloniaUI OÜ.