Skip to content

Proposal: Tabs Control #304

@stmoy

Description

@stmoy

The WinUI Team has opened a spec and PR for this feature.

Proposal: Tabs Control

Summary

The Tab control is a way to display a set of tabs and their respective content. Tab controls are useful for displaying several pages (or documents) of content while giving a user the capability to rearrange, open, or close new tabs.

Tabs in Edge

Rationale

As a UI paradigm, Tabs has been around for a long time, and can be found in everything from dialogs to browsers. The focus for this proposal is "document-style" tabs, which enables a user to rearrange, open, and close new tabs.

Tabs in the Edge browser
Tabs in Edge

Tabs in Visual Studio
Tabs in Visual Studio

Note that "static-style" tabs also exist as a paradigm. "Static-style" tabs are tabs that do not support user interaction beyond switching tabs. UWP already has a solution for static-style tabs in the form of Pivot and NavigationView.

Static-style tabs in WPF
Tabs in WPF

A lack of a proper Tab control has been a continual painpoint in UWP, particularly for developers attempting to migrate from WPF.

The XAML platform provides a number of ways to achieve "static-style" tabs in Pivot and top NavigationView. However, these solutions do not well support "document-style" tabs which support user reorder, opening, and closing tabs. The platform does demonstrate how to create "document-style" tabs in the Van Arsdel sample using top NavigationView:
Tabs in the Van Arsdel app

Although these workarounds have unblocked apps trying to create "document-style" tabs, they have a number of limitations, including:

  • Significant effort up to (and including) retemplating to build simple tabs
  • No built-in support for closing tabs
  • No built-in support for drag/drop into new windows
  • No built-in support for moving a tab from a window and combining it with another window
  • Limited keyboard and accessibility support

Fortunately, the Windows Community Toolkit has created a TabView control that helps address some of the aforementioned pain points.

TabView in WCT

However, the Windows Community Toolkit is a managed/C# project, meaning that customers that don't want to load the CLR or are particularly performance-focused cannot leverage the Windows Community Toolkit implementation.

The goal for this feature proposal is not to "reinvent the wheel" - instead, we hope to take the learnings from the WCT implementation and discussion and build a native control directly into WinUI.

Functional Requirements

# Feature Priority
1. User can switch tabs using common inputs (like ctrl+tab) Must
2. Control has a mode to close tabs Must
3. User can open new tabs Must
4. Control supports tab "tear off" Must
5. Control supports tab "recombination" (both into the same Tab group or between Tab groups) Must
6. Control supports tab reorder Must
7. Control supports data binding to a collection of tabs Must
8. Control supports a custom header/footer Must
9. When not all tabs fit, control provides affordance to access all tabs Must
10. Tab items can have a label and icon Should
11. Tab height, width, and template can be customized Should
12. The app may decide how size the tabs relative to each other (ie. equally sized, sized to content, etc.) Should
13. The control supports Tab Placement with tabs on the Left, Right, or Bottom. Could
14. App can specify specific "unclosable" tabs Could

Important Notes

To replicate the behavior of Microsoft Edge:

<TabControl TabWidthBehavior="Equal"
            CanCloseTabs="True"
            CloseButtonOverlay="OnHover"
            CanDragItems="True"
            CanReorderItems="True"
            TabDraggedOutside="OpenTabInNewWindow">
    <TabControl.TabFooter>
        <Button Content="+" Click="NewTab_Click" />
    </TabControl.TabFooter>
    ...
</TabControl>

The TabControl also supports databinding:

<TabControl ItemsSource="{x:Bind TabItemCollection}" />

TabControl properties and events

Property Type Description
CanCloseTabs bool Default value for the item if it doesn't specify a IsClosable value.
CloseButtonOverlay enum Describes the behavior of the close button. Values are {Auto, OnHover, Persistent}
ItemHeaderTemplate DataTemplate Default template for the item if no template specified.
SelectedTabWidth double The size of the selected tab header.
TabHeader object Content to the left of the tab strip.
TabHeaderTemplate DataTemplate Template for the Header.
TabFooter object Content to the far right of the tab strip.
TabFooterTemplate DataTemplate Template for the Footer.
TabActionContent object Content immediately to the right of the tabs
TabActionContentTemplate DataTemplate Template for the ActionContent.
TabWidthBehavior enum Specifies how the tabs should be sized. Values are {Actual, Equal, Compact}
Event Description
TabClosing Fires when a tab is about to be closed. Can be cancelled to prevent closure.
TabDraggedOutside Fires when a Tab is dragged outside of the Tab bar.

TabItem properties and events

Property Type Description
Content object The main content that appears in the tab.
Header object The content that appears inside the tab itself.
HeaderTemplate DataTemplate Template for the header object.
Icon IconElement Icon for the tab.
IsClosable bool Determines if the tab shows a close button.
Event Description
TabClosing Fires when a tab's close button is clicked.

Parts of a tab item

Position of TabHeader TabFooter and TabActionContent

Open Questions

1. Should Tab Tearoff be something that the control handles or that the app handles?
The app will handle it. We will have good samples showing how.

2. Should there be a built-in "Add new tab" button? (I suspect probably not, because the control doesn't own the collection of Tabs.)
The app will own the "Add tab" button. In the case of Terminal, for example, they will add a button with a dropdown. Adding an "Add" button doesn't add much value.

3. Should TabItem.Icon be IconElement or IconElementSource?
IconElement. IconElementSource is useful when the same icon could appear in multiple places in the tree, which isn't the case here.

  1. How can an app customize that the Selected tab looks like (ie. in Edge)?

  2. The API currently takes a lot of inspiration from the Toolkit. Are there any chances to iterate/improve?

Release Checklists

Prerelease readiness

  • Dev: quality review + code review done
  • Dev: test coverage added
  • Dev: initial accessibility review done
  • Dev: telemetry implemented
  • PM: spec up to date
  • PM: feature ready for feedback
  • PM: docs.microsoft.com updates ready

Stable release readiness

  • Dev: feature previously shipped in a prerelease NuGet package
  • Dev: Azure CI tests passing
  • Dev: accessibility review done
  • Dev: API review done
  • Dev: IDL attribute switched from preview to public
  • Dev: Add test coverage to the NugetReleaseTest test
  • PM: spec done
  • PM: glob/loc, privacy, security, license compliance ready
  • PM: customer validation done
  • PM: docs.microsoft.com updated
  • PM: Xaml Controls Gallery updated

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions