Skip to content

TabControl: Add (opt-in) navigation panel and custom header content#4026

Open
nicolaihenriksen wants to merge 13 commits intomasterfrom
issue3977
Open

TabControl: Add (opt-in) navigation panel and custom header content#4026
nicolaihenriksen wants to merge 13 commits intomasterfrom
issue3977

Conversation

@nicolaihenriksen
Copy link
Copy Markdown
Contributor

@nicolaihenriksen nicolaihenriksen commented Mar 26, 2026

Fixes #3977

This PR introduces 2 new features to the (horizontal) TabControl styles of MDIX:

image

The first feature, marked in $${\color{red}red}$$, is the ability to turn on a navigation panel which becomes visible when the tabs overflow the available screen real-estate.

The second feature, marked in $${\color{green}green}$$, is the ability to add custom header content to the right of the last visible tab. If the tabs are overflowing, it will sit next to the neighboring element (or window border in many/most cases).

UniformGrid style

TabControlUniformGridOverflow

VirtualizingStackPanel style

TabControlVirtualizingStackpanelOverflow

Navigation panel

The navigation panel can be enabled (only visible when overflowing) by adding the following AP at the call site:

<TabControl materialDesign:TabAssist.UseNavigationPanel="True" />

By default, the overflow buttons center vertically, but there is a "hook" built in which can be used to tweak this positioning to your liking. In case you want them to align with the bottom of a custom header content button, you could add the following:

<TabControl materialDesign:TabAssist.UseNavigationPanel="True"
            materialDesign:TabAssist.NavigationPanelMargin="8,15,8,0">
...
</TabControl>
image

Navigation panel placement

The placement of the navigation panel can be controlled by TabAssist.NavigationPanelPlacement attached property. This allows the buttons to be "split" (previous on the left side, and next on the right side; this is the default), or place both buttons on either the left or right side.

image image image

Navigation panel behavior

The behavior of the navigationpanel can be controlled by TabAssist.NavigationPanelBehavior attached property. This allows the navigation buttons to either scroll (a page) in either direction (this is the default), or select the next/previous (enabled) tab.

TabControlScrollBehavior

TabControlSelectBehavior

Custom header panel content

Custom content can be added to the right of the last visible tab by setting the TabAssist.HeaderPanelCustomContent attached property:

<TabControl materialDesign:TabAssist.UseNavigationPanel="True">
  <materialDesign:TabAssist.HeaderPanelCustomContent>
    <Button Content="+" Margin="8,0" />
  </materialDesign:TabAssist.HeaderPanelCustomContent>
</TabControl>
image

This example simply shows a button which could be used to add a new tab. Another use case for the custom content could be a drop-down menu giving (easy) access to all the available tabs. The TabAssist.IsOverflowing read-only attached property could be leveraged to control the visibility of this button:

<TabControl x:Name="MyTabControl"
            materialDesign:TabAssist.UseNavigationPanel="True">
  <materialDesign:TabAssist.HeaderPanelCustomContent>
    <custom:MyDropDownButton Visibility="{Binding ElementName="MyTabControl", Path="(materialDesign:TabAssist.IsOverflowing)", Converter="{StaticResource BooleanToVisibilityConverter}"}" />
  </materialDesign:TabAssist.HeaderPanelCustomContent>
</TabControl>
image

@nicolaihenriksen nicolaihenriksen marked this pull request as ready for review March 29, 2026 09:27
Copy link
Copy Markdown
Member

@Keboo Keboo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me. One minor UX thing I did notice was that at the end it appears to somewhat break the behavior of bringing the selected tab into view.

Image

BringIntoView direction is now dependent on the nav panel behavior. For scroll behavior, the current scroll position compared to the "next" tab determines the direction, whereas for select behavior, it is simply the index of the "next" tab that needs to be considered.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add "navigation buttons" for a (horizontally) scrollable TabControl

2 participants