Skip to content
Browse documentation

Tabs

A tab bar in its default, outline, pill, segmented and underline looks, as TabStrip and TabControl.

ExampleInteractive
Tabs — Avalonia UIKit
Live demo unavailable
<TabControl Classes="underline" Width="320" HorizontalAlignment="Left">
  <TabItem Header="Account">
    <TextBlock Text="Make changes to your account here." Margin="0,12" />
  </TabItem>
  <TabItem Header="Profile">
    <TextBlock Text="Edit your public profile." Margin="0,12" />
  </TabItem>
  <TabItem Header="Settings">
    <TextBlock Text="Change your preferences." Margin="0,12" />
  </TabItem>
</TabControl>

Usage

The theme covers TabStrip and TabStripItem (a bar on its own) and the strip of TabControl and TabItem (tabs with their content). The look is a class on the strip or control: the default look without one, or outline, pill, segmented or underline. Pill, segmented and underline show the selection with an indicator that springs to the selected tab on the UIKit.Spring.Move spring and reverses midway when the selection changes again; a pill's label fades in as the indicator slides. Sizes: xsmall, small, large (medium without one). Put icon-only on an item whose content is an icon. A tab shows a ring on keyboard focus only. Tabs can be closed, added and dragged with the uikit:Tabs attached properties (see Closing, adding and dragging).

Examples

The five looks; the last underline tab is disabled.

VariantsInteractive
Live demo unavailable
<StackPanel Spacing="16" HorizontalAlignment="Left">
  <TabStrip Width="320" SelectedIndex="0">
    <TabStripItem Content="Account" />
    <TabStripItem Content="Profile" />
    <TabStripItem Content="Settings" />
  </TabStrip>
  <TabStrip Classes="outline" Width="320" SelectedIndex="0">
    <TabStripItem Content="Account" />
    <TabStripItem Content="Profile" />
    <TabStripItem Content="Settings" />
  </TabStrip>
  <TabStrip Classes="pill" Width="320" SelectedIndex="0">
    <TabStripItem Content="Account" />
    <TabStripItem Content="Profile" />
    <TabStripItem Content="Settings" />
  </TabStrip>
  <TabStrip Classes="segmented" Width="320" SelectedIndex="0">
    <TabStripItem Content="Account" />
    <TabStripItem Content="Profile" />
    <TabStripItem Content="Settings" />
  </TabStrip>
  <TabStrip Classes="underline" Width="320" SelectedIndex="0">
    <TabStripItem Content="Account" />
    <TabStripItem Content="Profile" />
    <TabStripItem Content="Settings" IsEnabled="False" />
  </TabStrip>
</StackPanel>

The four sizes of a pill strip.

SizesInteractive
Live demo unavailable
<StackPanel Spacing="16" HorizontalAlignment="Left">
  <TabStrip Classes="pill xsmall" SelectedIndex="0">
    <TabStripItem Content="Account" />
    <TabStripItem Content="Profile" />
    <TabStripItem Content="Settings" />
  </TabStrip>
  <TabStrip Classes="pill small" SelectedIndex="0">
    <TabStripItem Content="Account" />
    <TabStripItem Content="Profile" />
    <TabStripItem Content="Settings" />
  </TabStrip>
  <TabStrip Classes="pill" SelectedIndex="0">
    <TabStripItem Content="Account" />
    <TabStripItem Content="Profile" />
    <TabStripItem Content="Settings" />
  </TabStrip>
  <TabStrip Classes="pill large" SelectedIndex="0">
    <TabStripItem Content="Account" />
    <TabStripItem Content="Profile" />
    <TabStripItem Content="Settings" />
  </TabStrip>
</StackPanel>

icon-only items in a pill and in a segmented strip.

Icon onlyInteractive
Live demo unavailable
<StackPanel Spacing="16" HorizontalAlignment="Left">
  <TabStrip Classes="pill" SelectedIndex="0">
    <TabStripItem Classes="icon-only">
      <PathIcon Data="{StaticResource UIKit.Icon.Inbox}" />
    </TabStripItem>
    <TabStripItem Classes="icon-only">
      <PathIcon Data="{StaticResource UIKit.Icon.Star}" />
    </TabStripItem>
    <TabStripItem Classes="icon-only">
      <PathIcon Data="{StaticResource UIKit.Icon.User}" />
    </TabStripItem>
  </TabStrip>
  <TabStrip Classes="segmented" SelectedIndex="0">
    <TabStripItem Classes="icon-only">
      <PathIcon Data="{StaticResource UIKit.Icon.Inbox}" />
    </TabStripItem>
    <TabStripItem Classes="icon-only">
      <PathIcon Data="{StaticResource UIKit.Icon.Star}" />
    </TabStripItem>
    <TabStripItem Classes="icon-only">
      <PathIcon Data="{StaticResource UIKit.Icon.User}" />
    </TabStripItem>
  </TabStrip>
</StackPanel>

Tabs that do not fit the bar scroll sideways, and the selected tab scrolls into view. The menu class adds a caret button at the end of the bar that lists the tabs, with the selected one checked and disabled ones disabled, and selects the one that is picked. uikit:Tabs.Prefix and uikit:Tabs.Suffix put content at the start and the end of the bar, outside the scrolling tabs; with a suffix or the menu the tabs end with 12px of space. They work the same on TabStrip and TabControl.

Six tabs in a 400px bar with a menu, a prefix and a suffix.

MenuInteractive
Live demo unavailable
<TabStrip Classes="menu" Width="400" VerticalAlignment="Top" SelectedIndex="0">
  <uikit:Tabs.Prefix>
    <StackPanel Orientation="Horizontal" Margin="4,0">
      <Button Classes="ghost xsmall icon-only"><PathIcon Data="{StaticResource UIKit.Icon.ChevronLeft}" /></Button>
      <Button Classes="ghost xsmall icon-only"><PathIcon Data="{StaticResource UIKit.Icon.ChevronRight}" /></Button>
    </StackPanel>
  </uikit:Tabs.Prefix>
  <uikit:Tabs.Suffix>
    <StackPanel Orientation="Horizontal" Margin="4,0">
      <Button Classes="ghost xsmall icon-only"><PathIcon Data="{StaticResource UIKit.Icon.Inbox}" /></Button>
      <Button Classes="ghost xsmall icon-only"><PathIcon Data="{StaticResource UIKit.Icon.Ellipsis}" /></Button>
    </StackPanel>
  </uikit:Tabs.Suffix>
  <TabStripItem Content="Account" />
  <TabStripItem Content="Profile" />
  <TabStripItem Content="Settings" />
  <TabStripItem Content="Billing" />
  <TabStripItem Content="Notifications" IsEnabled="False" />
  <TabStripItem Content="Integrations" />
</TabStrip>

Closing, adding and dragging

These attached properties go on a TabStrip or a TabControl. They change the list the tabs come from: its ItemsSource, which must be a list that can change (such as an ObservableCollection), or its Items. Tabs whose list cannot change are not closed or moved.

Attached propertyEffect
uikit:Tabs.ClosableA close button in each tab, as GPUI Kit's closable tab: the tab is padded px_2 and ends with a ghost xsmall Close button. On the strip it applies to every tab; on a tab, to that tab.
uikit:Tabs.NewTabFactoryAn add button after the last tab. It adds the item the function returns at the end and selects it.
uikit:Tabs.ReorderableTabs are dragged along the bar to reorder them: the dragged tab follows the pointer, the others make room, and the drop moves its item. The dragged tab has the :dragging pseudo-class and is drawn over the tabs it passes: with the indicator, or, in outline and underline, with the active tab's background. A bar whose tabs overflow scrolls while the tab is held at its end.
uikit:Tabs.DragGroupWith Reorderable, a tab dragged onto another bar of the same group moves to it. Bars in different windows exchange tabs; in a browser, only bars in the same view do.
uikit:Tabs.DetachedWindowFactoryWith a DragGroup, a tab dragged off every bar of its group moves into the window the function returns, which follows the pointer until the drop. In a window only.

The close button raises uikit:Tabs.TabClosing on the strip before it removes the tab; set Cancel to keep it. Closing the selected tab selects the next one.

A closable tab bar whose add button opens new tabs, and whose tabs can be reordered. The last tab cannot be closed.

ClosableInteractive
Live demo unavailable
<TabControl Name="Tabs" Width="480" HorizontalAlignment="Left"
            uikit:Tabs.Closable="True" uikit:Tabs.Reorderable="True"
            Loaded="OnLoaded">
  <TabItem Header="Account">
    <TextBlock Text="Make changes to your account here." Margin="0,12" />
  </TabItem>
  <TabItem Header="Profile">
    <TextBlock Text="Edit your public profile." Margin="0,12" />
  </TabItem>
  <TabItem Header="Settings">
    <TextBlock Text="Change your preferences." Margin="0,12" />
  </TabItem>
</TabControl>
Closable.axaml.cs
Tabs.SetNewTabFactory(tabs, () => new TabItem { Header = $"Tab {++added}", Content = new TextBlock { Text = "A new tab." } });
Tabs.AddTabClosingHandler(tabs, (_, args) => args.Cancel = tabs.ItemCount == 1);

Tabs reordered by dragging.

ReorderInteractive
Live demo unavailable
<TabStrip Classes="pill" SelectedIndex="0" uikit:Tabs.Reorderable="True">
  <TabStripItem Content="Account" />
  <TabStripItem Content="Profile" />
  <TabStripItem Content="Settings" />
  <TabStripItem Content="Billing" />
  <TabStripItem Content="Notifications" />
</TabStrip>

Two bars of one group: drag a tab from one to the other.

Drag groupInteractive
Live demo unavailable
<StackPanel Spacing="16" HorizontalAlignment="Left">
  <TabStrip Width="360" SelectedIndex="0"
            uikit:Tabs.Reorderable="True" uikit:Tabs.DragGroup="files">
    <TabStripItem Content="index.html" />
    <TabStripItem Content="style.css" />
    <TabStripItem Content="app.js" />
  </TabStrip>
  <TabStrip Width="360" SelectedIndex="0"
            uikit:Tabs.Reorderable="True" uikit:Tabs.DragGroup="files">
    <TabStripItem Content="README.md" />
    <TabStripItem Content="LICENSE" />
  </TabStrip>
</StackPanel>

Dragging tabs out into windows

uikit:Tabs.DetachedWindowFactory gets the item of the tab being dragged off and returns the window it moves to. The window must hold a TabStrip or TabControl of the same group, empty and reorderable; the tab is put in it, and the window is shown under the pointer and follows it. Dragged over a bar of the group, the tab moves back and the window is hidden. A window made this way closes when its last tab is dragged out or closed, and dragging its only tab moves the window itself. Windows the app opens itself stay open when their bars empty.

MainWindow.axaml.cs
Tabs.SetDetachedWindowFactory(documents, _ => NewDocumentWindow());

static Window NewDocumentWindow()
{
    var tabs = new TabControl();
    Tabs.SetClosable(tabs, true);
    Tabs.SetReorderable(tabs, true);
    Tabs.SetDragGroup(tabs, "documents");
    Tabs.SetDetachedWindowFactory(tabs, _ => NewDocumentWindow());
    return new Window { Title = "Documents", Width = 640, Height = 400, Content = tabs };
}

A page has no windows, so this does not run in the live demos.