Install Tabalonia via NuGet
mainInstall the Tabalonia library as a NuGet package to enable draggable, detachable, and dockable tabs in your Avalonia application.
Install-Package Tabalonia
# Or
dotnet add package Tabaloniarepository·main·Indexed 42 days ago
https://github.com/egorozh/tabaloniaAn Avalonia port of Draggablz that provides draggable, detachable, and dockable tab items. It enables Chrome-style interactions, allowing users to reorder tabs, tear them off into floating windows, or dock them into other windows using the TabsControl.
Install the Tabalonia library as a NuGet package to enable draggable, detachable, and dockable tabs in your Avalonia application.
Install-Package Tabalonia
# Or
dotnet add package TabaloniaInstead of re-templating, you can restyle the CustomTheme by overriding specific brush resources in your App.axaml.
```xml
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.ThemeDictionaries>
<ResourceDictionary x:Key="Dark">
<SolidColorBrush x:Key="SelectedTabItemBackgroundBrush" Color="#1E1E2E" />
</ResourceDictionary>
</ResourceDictionary.ThemeDictionaries>
</ResourceDictionary>
</Application.Resources>Full list of keys is available in Themes/Custom/Brushes.axaml.
To use Tabalonia, you must add a theme to your App.axaml. You can choose between the CustomTheme (with light/dark variants) or the FluentTheme (Fluent-styled variant).
<!-- Using CustomTheme -->
<Application xmlns="https://github.com/avaloniaui"
xmlns:custom="clr-namespace:Tabalonia.Themes.Custom;assembly=Tabalonia">
<Application.Styles>
<FluentTheme />
<custom:CustomTheme />
</Application.Styles>
</Application>
<!-- Using FluentTheme variant -->
<Application xmlns="https://github.com/avaloniaui"
xmlns:fluent="clr-namespace:Tabalonia.Themes.Fluent;assembly=Tabalonia">
<Application.Styles>
<fluent:FluentTheme />
</Application.Styles>
</Application>The TabsControl is used similarly to a standard Avalonia TabControl.
Important: The ItemsSource must implement IList (such as ObservableCollection<T>) because adding, closing, reordering, and dragging tabs between windows directly mutates the collection.
<Window xmlns:controls="clr-namespace:Tabalonia.Controls;assembly=Tabalonia">
<controls:TabsControl ItemsSource="{Binding TabItems}"
NewItemFactory="{Binding NewItemFactory}"
FixedHeaderCount="1">
<TabControl.ItemTemplate>
<DataTemplate DataType="vm:TabItemViewModel">
<TextBlock Text="{Binding Header}" />
</DataTemplate>
</TabControl.ItemTemplate>
<TabControl.ContentTemplate>
<DataTemplate DataType="vm:TabItemViewModel">
<TextBlock Text="{Binding SimpleContent}" />
</DataTemplate>
</TabControl.ContentTemplate>
</controls:TabsControl>
</Window>Tabalonia allows tabs to be torn off into new windows or docked into other TabsControl instances.
```csharp
// Customizing the window created when a tab is torn off
tabsControl.DetachedWindowFactory = tabs => new MyToolWindow { Content = tabs };| Property | Type | Default | Description |
|---|---|---|---|
EnableTabDetaching | bool | true | Allows dragging a tab out of the strip into a new floating window |
EnableTabAttaching | bool | true | Allows this strip to give away and accept tabs dragged from other TabsControls |
DetachTriggerDistance | double | 32 | How far (px) the pointer must leave the strip before the tab tears off |
DetachedWindowFactory | Func<TabsControl, Window>? | null | Creates the host window for a detached tab; by default the source window's size, background and decorations are cloned |
Use these properties on TabsControl to adjust the visual layout of the tab strip:
| Property | Type | Default | Description |
|---|---|---|---|
TabItemWidth | double | 140 | Maximum tab width; tabs shrink evenly when the strip runs out of space |
AdjacentHeaderItemOffset | double | 0 | Horizontal offset between neighbouring tabs (negative values overlap them) |
FixedHeaderCount | int | 0 | Number of leading tabs that are pinned: they can't be dragged, closed or displaced |
LeftContent | object? | null | Arbitrary content rendered to the left of the tab strip |
RightContent | object? | null | Arbitrary content rendered to the right of the tab strip |
Tabalonia provides built-in mechanisms for adding and closing tabs. You can control visibility and provide factories for new items.
```csharp
// Handling tab closing events to prevent closing unsaved documents
tabs.TabClosing += (_, e) =>
{
if (e.Item is DocumentViewModel { IsDirty: true })
e.Cancel = true; // keep the tab open
};
tabs.TabClosed += (_, e) => Console.WriteLine($"Closed: {e.Item}");
// Prevent the window from closing when the last tab is closed
tabs.LastTabClosedAction = (_, e) => { /* e.Window stays open */ };| Member | Type | Description |
|---|---|---|
ShowDefaultAddButton | bool | Shows the built-in "+" button after the last tab (Default: true) |
ShowDefaultCloseButton | bool | Shows the "×" button on each tab (except fixed ones) (Default: true) |
NewItemFactory | Func<object>? | Creates the model for a new tab when the add button is clicked |
NewItemAsyncFactory | Func<Task<object>>? | Async variant; takes precedence over NewItemFactory |
AddItemCommand | ICommand | (Read-only) Adds a tab via the factory — bind it from your own buttons |
CloseItemCommand | ICommand | (Read-only) Closes the tab passed as the command parameter (DragTabItem) |
TabClosing | EventHandler<TabClosingEventArgs>? | Raised before a tab closes; set e.Cancel = true to keep it open |
TabClosed | EventHandler<TabClosedEventArgs>? | Raised after a tab closed; e.Item is the removed model |
LastTabClosedAction | EventHandler<CloseLastTabEventArgs>? | Action taken when the last tab is removed; default closes the window (e.Window) |
The empty areas in the tab strip act as window-drag handles (double-click to restore/maximize). This is useful when using ExtendClientAreaToDecorationsHint="True".
| Property | Default | Description |
|---|---|---|
| `LeftThumbWidth` | `80` (macOS), `4` (elsewhere) | Width of the drag area before the first tab |
| `RightThumbWidth` | `160` (Windows), `50` (elsewhere) | Width of the drag area after the add button |