Devolutions.AvaloniaTheme.Linux
2026.8.27
Prefix Reserved
dotnet add package Devolutions.AvaloniaTheme.Linux --version 2026.8.27
NuGet\Install-Package Devolutions.AvaloniaTheme.Linux -Version 2026.8.27
<PackageReference Include="Devolutions.AvaloniaTheme.Linux" Version="2026.8.27" />
<PackageVersion Include="Devolutions.AvaloniaTheme.Linux" Version="2026.8.27" />
<PackageReference Include="Devolutions.AvaloniaTheme.Linux" />
paket add Devolutions.AvaloniaTheme.Linux --version 2026.8.27
#r "nuget: Devolutions.AvaloniaTheme.Linux, 2026.8.27"
#:package Devolutions.AvaloniaTheme.Linux@2026.8.27
#addin nuget:?package=Devolutions.AvaloniaTheme.Linux&version=2026.8.27
#tool nuget:?package=Devolutions.AvaloniaTheme.Linux&version=2026.8.27
Custom Avalonia Themes developed by Devolutions
Linux Theme [Work in Progress]
This theme is currently based on Avalonia.Themes.Fluent, both as a fallback for any controls not covered yet and as starting point for our style definitions targeting a Linux look similar to Ubuntuโs default โYaruโ GTK theme..
While we are prioritizing controls for Devolutions Remote Desktop Manager, we welcome contributions from the Avalonia community to add more controls.
- Installation
- Styled Controls
- Available in the current build
- ๐ง In progress ...
- Dark mode support
- ๐ฎ Next on the road map ...
Installation
Avalonia 12 required. Packages
2026.6.17-avalonia12and later require Avalonia 12. The last stable release compatible with Avalonia 11 is2026.6.16.
Install the Devolutions.AvaloniaTheme.Linux package via NuGet:
Install-Package Devolutions.AvaloniaTheme.Linux
or .NET
dotnet add package Devolutions.AvaloniaTheme.Linux
In your App.axaml, replace the existing theme (e.g. <FluentTheme /> or <SimpleTheme />) with the Linux theme:
<Application ...>
<Application.Styles>
<DevolutionsLinuxYaruTheme />
</Application.Styles>
</Application>
Menu pack (menu controls only)
Use the menu pack when you only want Linux menu styling but not the full <DevolutionsLinuxYaruTheme />
(e.g. to give consistent Menu chrome to custom-branded sections of your app).
The Linux theme has no OS-dependent sub-themes, so โ unlike the MacOS pack, which has to pick between its classic and LiquidGlass variants at runtime โ this pack is a plain style include, the same shape as the DevExpress pack.
<Application ...>
<Application.Styles>
<FluentTheme />
<StyleInclude Source="avares://Devolutions.AvaloniaTheme.Linux/Controls/MenuPack.styles.axaml" />
</Application.Styles>
</Application>
Exact menu pack URI:
avares://Devolutions.AvaloniaTheme.Linux/Controls/MenuPack.styles.axaml
Prerequisites and caveats:
FluentThememust be loaded application-wide, inApplication.Stylesโ not scoped to a subtree. The Linux control themes build on Fluent's base templates, andHorizontalMenuItemderives from Fluent'sFluentTopLevelMenuItem, which is resolved when the menu template is built.- This pack includes styling for
ContextMenu,MenuFlyoutPresenter,Menu,MenuItem, and the menu-specific helper styles (Menu.styles.axaml,Separator.styles.axaml,MenuSvg.styles.axaml). - If you need full control coverage, use
<DevolutionsLinuxYaruTheme />instead.
Resource contract
All menu tokens live in a single shared file, Accents/MenuResources.axaml, which is included by both the
full theme and the menu pack. There is one source of truth, so the pack can never drift from the full theme.
Two rules make the pack safe to layer over a host theme you do not control:
Every menu token the pack owns is prefixed
LinuxMenuโ no token can collide with, or be silently overridden by, the host theme's keys.This applies to the tokens, not to every resource in the pack. The pack also ships
ControlThemes, and those are deliberately not prefixed: the implicit ones ({x:Type MenuItem},{x:Type Menu},{x:Type ContextMenu},{x:Type MenuFlyoutPresenter}) must keep theirx:Typekeys, since that is the mechanism by which the pack restyles menus at all. Two named ones โHorizontalMenuItemandHorizontalMenuFlyoutPresenterโ are also unprefixed and share their names with the other Devolutions themes; whichever is nearest in scope wins, so the pack's versions apply within the scope the pack is added to.Values are pinned literals, never aliases. Menu tokens do not resolve through generic theme-wide or Fluent-owned keys. A host theme that redefines e.g.
MenuFlyoutItemForegroundorFlyoutThemeMaxWidthcannot move menu visuals.
Rule 2 mattered more here than for the other packs. The Linux menu templates were derived from Fluent and read
Fluent's own generic keys directly (MenuFlyoutItemBackground, MenuFlyoutPresenterBackground,
CheckMarkPathData, ...). That is invisible under the full theme, but layered over another theme every one of
those keys resolved to the host's value, so the "Linux" menus rendered in the host's colours. Those templates
now read LinuxMenu* tokens only.
Inherited from the host (by design):
| Key | Why |
|---|---|
FluentTopLevelMenuItem |
Base for HorizontalMenuItem (the horizontal TextBox context flyout). Re-basing it would mean duplicating Fluent's top-level item template, which the pack deliberately avoids. |
Typography is pinned, not inherited. LinuxMenuFontFamily / LinuxMenuFontSize / LinuxMenuFontWeight are
owned by the pack. The point of the pack is that menus in a branded or opted-out section still match the
platform-themed menus elsewhere in the same app; inheriting the host's font defeats that, and pinning also keeps
menu geometry identical across hosts (font metrics change row heights).
Row geometry, typography and normal-state colours are applied at Style level, not only in the MenuItem
ControlTheme. Host themes set menu metrics with Styles of their own, and in Avalonia a Style setter
outranks a ControlTheme setter โ so a ControlTheme alone would let the host resize menu rows, restyle their
text, or recolour them.
This sealing is applied in two places, because one selector cannot cover both: popup rows and submenu items are
descendants of ContextMenu / MenuFlyoutPresenter / MenuItem, whereas menu-bar items are direct children
of Menu and would otherwise be left exposed. The two blocks pin the same typography but different geometry,
since menu-bar items have their own padding. Only the normal state is sealed there; hover / selected /
disabled colours are applied to template children, which a host MenuItem style cannot reach.
This sealing lives in MenuPack.Sealing.styles.axaml and is included only by the standalone pack, not by the full
DevolutionsLinuxYaruTheme. Inside the full theme, app-level Style overrides on menu items are expected to win,
the same as for any other themed control. To override a pack-sealed property from a consuming app, your override
selector must also match a pseudo-class (e.g. :not(:separator)) to reach the same StyleTrigger priority tier, and
should live in a scope nested inside the one hosting the pack (Avalonia resolves same-priority ties by scope โ inner
wins โ before declaration order).
SVG menu icons are recoloured by the pack. Menu icons ship with an embedded fill, so
MenuSvg.styles.axaml applies LinuxMenuSvgItemDefaultCss / LinuxMenuSvgItemDisabledCss per variant. The full
theme includes the same file from GlobalStyles.axaml, so the two cannot drift.
The pack styles menu content only. It deliberately does not ship a Separator ControlTheme: that resource
is keyed {x:Type Separator}, so merging it would restyle every separator in your app rather than just menu
ones. Menu separators instead reuse the host's separator template โ identical across Fluent, MacOS, Linux and
DevExpress โ with every template-bound property pinned inside the menu-scoped selector.
Overriding a token. Because tokens are prefixed, you can retarget any single value without affecting the rest of your app:
<Application ...>
<Application.Resources>
<SolidColorBrush x:Key="LinuxMenuSeparatorBrush" Color="#ff0000" />
</Application.Resources>
<Application.Styles>
<FluentTheme />
<StyleInclude Source="avares://Devolutions.AvaloniaTheme.Linux/Controls/MenuPack.styles.axaml" />
</Application.Styles>
</Application>
The two go in different collections โ the token override is a resource, the pack is a style โ and the relative order of the collections does not matter.
The override must not sit in an outer scope relative to the pack. Resource lookup walks up from the
control and stops at the first match, and an element's Resources are consulted before its Styles. So an
override works when it sits on the same element that carries the pack (as above) or on a descendant, but is
silently ignored if the pack is added lower down โ e.g. pack on a UserControl, override on the Window.
In that case the pack's own token is found first and your value never applies.
These rules are enforced by LinuxMenuPackContractTests in the visual test project, which asserts that every
LinuxMenu* token resolves identically under the full theme and under "pack over a foreign host", that a hostile
host theme cannot leak into any of them, and that the menu templates never read an unowned resource key.
Styled Controls
Below are some screenshots from the SampleApp test and demo pages - feel free to check out the code there for more detailed usage examples. For an always up-to-date visual reference you can also browse the baseline screenshots.
| <h3>AdornerLayer</h3> | |
| <h3>AutoCompleteBox</h3> | |
| <h3>Button</h3> | |
| <h3>ButtonSpinner</h3> | |
| <h3>Calendar</h3> | |
| <h3>CalendarButton</h3> | |
| <h3>CalendarDatePicker</h3> | |
| <h3>CalendarDayButton</h3> | |
| <h3>CalendarItem</h3> | |
| <h3>CaptionButtons</h3> | |
| <h3>Carousel</h3> | |
| <h3>CheckBox</h3> | |
| โ | <h3>ComboBox</h3> <h4>ComboBoxItem</h4> |
| <img alt="ComboBox" src="https://github.com/user-attachments/assets/dffff816-a0d8-4dc1-8906-ae5b4946690c" style="width: 360px; max-width: 100%;" /> <img alt="ComboBox - dark mode" src="https://github.com/user-attachments/assets/3010743c-f9dd-4446-9a31-cc717504cfc6" style="width: 360px; max-width: 100%;" /> | |
| <h3>ContextMenu</h3> | |
| <h3>DataGrid</h3> | |
| <h3>DataValidationErrors</h3> | |
| <h3>DatePicker</h3> | |
| <h3>DateTimePickerShared</h3> | |
| <h3>DropDownButton</h3> | |
| <h3>EmbeddableControlRoot</h3> | |
| <h3>Expander</h3> | |
| <h3>FluentControls</h3> | |
| <h3>FlyoutPresenter</h3> | |
| <h3>GridSplitter</h3> | |
| <h3>HeaderedContentControl</h3> | |
| <h3>HyperlinkButton</h3> | |
| <h3>ItemsControl</h3> | |
| <h3>Label</h3> | |
| <h3>ListBox</h3> | |
| <h3>ListBoxItem</h3> | |
| <h3>ManagedFileChooser</h3> | |
| <h3>Menu</h3> | |
| <h3>MenuFlyoutPresenter</h3> | |
| <h3>MenuItem</h3> | |
| <h3>MenuScrollViewer</h3> | |
| <h3>NotificationCard</h3> | |
| <h3>NumericUpDown</h3> | |
| <h3>OverlayPopupHost</h3> | |
| <h3>PathIcon</h3> | |
| <h3>PopupRoot</h3> | |
| <h3>ProgressBar</h3> | |
| <h3>RadioButton</h3> | |
| <h3>RefreshContainer</h3> | |
| <h3>RefreshVisualizer</h3> | |
| <h3>RepeatButton</h3> | |
| <h3>ScrollViewer</h3> <h4>ScrollBar</h4> | |
| <h3>SelectableTextBlock</h3> | |
| <h3>Separator</h3> | |
| <h3>Slider</h3> | |
| <h3>SplitButton</h3> | |
| <h3>SplitView</h3> | |
| <h3>TabControl</h3> <h4>TabItem<h4> | |
| <h3>TabStrip</h3> | |
| <h3>TabStripItem</h3> | |
| <h3>TextBox</h3> | |
| <h3>TextSelectionHandle</h3> | |
| <h3>ThemeVariantScope</h3> | |
| <h3>TimePicker</h3> | |
| <h3>TitleBar</h3> | |
| <h3>ToggleButton</h3> | |
| <h3>ToggleSwitch</h3> | |
| <h3>ToolTip</h3> | |
| <h3>TransitioningContentControl</h3> | |
| <h3>TreeView</h3> <h4>TreeViewItem<h4> | |
| <h3>Window</h3> | |
| <h3>WindowNotificationManager</h3> | |
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- Avalonia (>= 12.0.2)
- Avalonia.Controls.ColorPicker (>= 12.0.2)
- Avalonia.Controls.DataGrid (>= 12.0.0)
- Avalonia.Themes.Fluent (>= 12.0.2)
- Devolutions.AvaloniaControls (>= 2026.8.25)
- Svg.Controls.Avalonia (>= 12.0.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories (1)
Showing the top 1 popular GitHub repositories that depend on Devolutions.AvaloniaTheme.Linux:
| Repository | Stars |
|---|---|
|
Devolutions/UniGetUI
UniGetUI: The Graphical Interface for your package managers. Could be terribly described as a package manager manager to manage your package managers
|
| Version | Downloads | Last Updated |
|---|---|---|
| 2026.8.27 | 39 | 8/27/2026 |
| 2026.8.25 | 732 | 8/25/2026 |
| 2026.8.10 | 96 | 8/10/2026 |
| 2026.7.30 | 3,301 | 7/30/2026 |
| 2026.7.22 | 853 | 7/22/2026 |
| 2026.7.14 | 786 | 7/14/2026 |
| 2026.7.10 | 112 | 7/10/2026 |
| 2026.7.6 | 646 | 7/6/2026 |
| 2026.6.29 | 122 | 6/29/2026 |
| 2026.6.23 | 196 | 6/23/2026 |
| 2026.6.17-avalonia12 | 216 | 6/17/2026 |
| 2026.6.16 | 956 | 6/16/2026 |
| 2026.6.10 | 423 | 6/10/2026 |
| 2026.6.2 | 416 | 6/2/2026 |
| 2026.5.14 | 766 | 5/14/2026 |
| 2026.5.8 | 581 | 5/8/2026 |
| 2026.4.30 | 309 | 4/30/2026 |
| 2026.4.22 | 440 | 4/22/2026 |
| 2026.4.17 | 134 | 4/17/2026 |
| 2026.4.16 | 128 | 4/16/2026 |
BREAKING: 2026.6.23 requires Avalonia 12. Last Avalonia 11 stable release: 2026.6.16.
See https://github.com/Devolutions/avalonia-extensions/blob/master/src/Devolutions.AvaloniaTheme.Linux/CHANGELOG.md