Simple Tabs
Content One
<MudTabs Elevation="2" Rounded="true" ApplyEffectsToContainer="true" PanelClass="pa-6"> <MudTabPanel Text="Tab One"> <MudText>Content One</MudText> </MudTabPanel> <MudTabPanel Text="Tab Two"> <MudText>Content Two</MudText> </MudTabPanel> <MudTabPanel Text="Tab Three"> <MudText>Content Three</MudText> </MudTabPanel> <MudTabPanel Text="Tab Disabled" Disabled="true"> <MudText>Content Disabled</MudText> </MudTabPanel> </MudTabs>
Icon Tabs
Icons can be added alongside text in the tabs to enhance visuals.
<MudTabs Outlined="true"> <MudTabPanel Text="Api" Icon="@Icons.Material.Filled.Api"/> <MudTabPanel Icon="@Icons.Material.Filled.Build"/> <MudTabPanel Text="Bug Report" Icon="@Icons.Material.Filled.BugReport"/> </MudTabs>
Tabs Position
The position of the tab bar can be changed with the Position
property.
Content One
<MudTabs Outlined="true" Position="" Rounded="true" Border="true" ApplyEffectsToContainer="true" Class="mt-8" PanelClass="pa-6"> <MudTabPanel Text="Item One"> <MudText>Content One</MudText> </MudTabPanel> <MudTabPanel Text="Item Two"> <MudText>Content Two</MudText> </MudTabPanel> <MudTabPanel Text="Item Three"> <MudText>Content Three</MudText> </MudTabPanel> </MudTabs> <MudSelect Label="Tabs Position" @bind-Value="Position" Variant="Variant.Outlined"> <MudSelectItem T="Position" Value="@Position.Top">Top</MudSelectItem> <MudSelectItem T="Position" Value="@Position.Start">Start</MudSelectItem> <MudSelectItem T="Position" Value="@Position.Left">Left</MudSelectItem> <MudSelectItem T="Position" Value="@Position.Right">Right</MudSelectItem> <MudSelectItem T="Position" Value="@Position.End">End</MudSelectItem> <MudSelectItem T="Position" Value="@Position.Bottom">Bottom</MudSelectItem> </MudSelect>
@code { public Position Position { get; set; } = Position.Left; private void OnSelectedValue(Position value) { switch (value) { case Position.Top: Position = Position.Top; break; case Position.Start: Position = Position.Start; break; case Position.Left: Position = Position.Left; break; case Position.Right: Position = Position.Right; break; case Position.End: Position = Position.End; break; case Position.Bottom: Position = Position.Bottom; break; } } }
Centered
The Centered
property aligns the tabs in the middle of the container.
<MudTabs Centered="_centered" Color="Color.Primary"> <MudTabPanel Text="One"/> <MudTabPanel Text="Two"/> <MudTabPanel Text="Three"/> </MudTabs> <MudSwitch @bind-Value="_centered" Color="Color.Primary">Centered</MudSwitch>
@code{ bool _centered = true; }
Tab Width
The MinimumTabWidth
property defines a minimum width for each tab.
<MudStack> <MudTabs Outlined="true" MinimumTabWidth="20px"> <MudTabPanel Icon="@Icons.Material.Filled.Build" /> <MudTabPanel Text="Api" Icon="@Icons.Material.Filled.Api" /> <MudTabPanel Icon="@Icons.Material.Filled.Settings" /> </MudTabs> <MudTabs Outlined="true" MinimumTabWidth="20px" Position="Position.Left"> <MudTabPanel Icon="@Icons.Material.Filled.Build" /> <MudTabPanel Text="Api" Icon="@Icons.Material.Filled.Api" /> <MudTabPanel Icon="@Icons.Material.Filled.Settings" /> </MudTabs> </MudStack>
Tooltips
Tooltips can be added which will activate when the user hovers over the tab.
<MudTabs> <MudTabPanel Text="Item One" ToolTip="ToolTip One" /> <MudTabPanel Text="Item Two" ToolTip="ToolTip Two" /> <MudTabPanel Text="Item Three" ToolTip="ToolTip Three" /> <MudTabPanel Text="Item Disabled" ToolTip="ToolTip Disabled" Disabled="true" /> </MudTabs>
Badges
Badges can be applied to icons or text within tabs for additional context.
<MudTabs Elevation="2" Rounded="true" Centered="true"> <MudTabPanel Icon="@Icons.Material.Filled.Api" BadgeData='"live"' BadgeColor="Color.Info" /> <MudTabPanel Icon="@Icons.Material.Filled.Build" BadgeData='"..."' /> <MudTabPanel Icon="@Icons.Material.Filled.BugReport" BadgeData='"99+"' BadgeColor="Color.Error" /> <MudTabPanel Icon="@Icons.Material.Filled.AccessTime" BadgeData='string.Empty' BadgeDot="true" BadgeColor="Color.Success" /> </MudTabs> <MudTabs Elevation="2" Rounded="true" Centered="true" Class="my-6" Color="Color.Dark"> <MudTabPanel Icon="@Icons.Material.Filled.Api" Text="API" BadgeData='"!"' BadgeColor="Color.Error" /> <MudTabPanel Icon="@Icons.Material.Filled.Build" Text="Build" BadgeData="1" BadgeColor="Color.Success" /> <MudTabPanel Icon="@Icons.Material.Filled.BugReport" Text="Bugs" BadgeData="0" /> <MudTabPanel Icon="@Icons.Material.Filled.AccessTime" Text="Timing" BadgeDot="true" BadgeColor="Color.Error" /> </MudTabs> <MudTabs Elevation="2" Rounded="true" Centered="true"> <MudTabPanel Text="API" BadgeData='"S"' /> <MudTabPanel Text="Build" BadgeData='"..."' BadgeColor="Color.Dark" /> <MudTabPanel Text="Bugs" BadgeData='"N"' /> <MudTabPanel Text="Timing" BadgeDot="true" BadgeColor="Color.Primary" /> </MudTabs>
Scrolling Tabs
If the total size of all tabs exceeds the size of the container, scroll buttons are automatically added.
The AlwaysShowScrollButtons
property keeps the scroll buttons visible at all times.
<MudTabs Elevation="4" Color="@Color.Secondary"> <MudTabPanel Text="One" /> <MudTabPanel Text="Two" /> <MudTabPanel Text="Three" /> <MudTabPanel Text="Four" /> <MudTabPanel Text="Five" /> <MudTabPanel Text="Six" /> <MudTabPanel Text="Seven" /> <MudTabPanel Text="Eight" /> <MudTabPanel Text="Nine" /> <MudTabPanel Text="Ten" /> <MudTabPanel Text="Eleven" /> <MudTabPanel Text="Thirteen" /> </MudTabs> <MudTabs Elevation="4" AlwaysShowScrollButtons="true" Color="@Color.Info" Class="mt-4"> <MudTabPanel Text="One" /> <MudTabPanel Text="Two" /> <MudTabPanel Text="Three" /> </MudTabs>
Scroll Icons
The scroll icons can be customized using the PrevIcon
and NextIcon
properties.
<MudTabs Elevation="4" Color="@Color.Success" PrevIcon="@Icons.Material.Filled.SkipPrevious" NextIcon="@Icons.Material.Filled.SkipNext"> <MudTabPanel Text="One" /> <MudTabPanel Text="Two" /> <MudTabPanel Text="Three" /> <MudTabPanel Text="Four" /> <MudTabPanel Text="Five" /> <MudTabPanel Text="Six" /> <MudTabPanel Text="Seven" /> <MudTabPanel Text="Eight" /> <MudTabPanel Text="Nine" /> <MudTabPanel Text="Ten" /> <MudTabPanel Text="Eleven" /> <MudTabPanel Text="Thirteen" /> </MudTabs>
Render Fragments
Custom tab header content can be provided for special scenarios.
Specify only TabContent
to customize the tab content, or specify TabWrapperContent
to provide a wrapper around the entire tab header.
The header of the active tab can be customized using ActiveTabClass
.
Custom tab content only
<MudTabs Elevation="1" Rounded="true" PanelClass="pa-6" ActiveTabClass="border-solid border-2 mud-border-primary"> <MudTabPanel> <ChildContent> <MudText>Custom tab content only</MudText> </ChildContent> <TabContent> Item One </TabContent> </MudTabPanel> <MudTabPanel> <ChildContent> <MudText>Both custom tab and wrapper content</MudText> </ChildContent> <TabWrapperContent> <MudTooltip Text="ToolTip Two"> @context </MudTooltip> </TabWrapperContent> <TabContent> <MudText Typo="Typo.h6">Item Two</MudText> </TabContent> </MudTabPanel> <MudTabPanel Text="Item Three"> <ChildContent> <MudText>Custom wrapper content only</MudText> </ChildContent> <TabWrapperContent> <MudTooltip Text="ToolTip Three"> @context </MudTooltip> </TabWrapperContent> </MudTabPanel> </MudTabs>
Set Active Panel
Programmatic selection of an active tab is supported through bindings.
Set Active by Index
Set Active by Instance
Set Active by TabPanel ID
<MudTabs Elevation="1" Rounded="true" @ref="tabs"> <MudTabPanel Text="One" @ref="panel01" ID="@("pn_one")" /> <MudTabPanel Text="Two" @ref="panel02" ID="@("pn_two")" /> <MudTabPanel Text="Three" @ref="panel03" ID="@("pn_three")" /> </MudTabs> <MudText GutterBottom="true" Align="Align.Center" Class="mt-8"><b>Set Active by Index</b></MudText> <div class="d-flex justify-center"> <MudButton Variant="@Variant.Filled" Color="Color.Primary" OnClick="() => Activate(0)">Index 0</MudButton> <MudButton Variant="@Variant.Filled" Color="Color.Primary" OnClick="() => Activate(1)" Class="mx-2">Index 1</MudButton> <MudButton Variant="@Variant.Filled" Color="Color.Primary" OnClick="() => Activate(2)">Index 2</MudButton> </div> <MudText GutterBottom="true" Align="Align.Center" Class="mt-4"><b>Set Active by Instance</b></MudText> <div class="d-flex justify-center"> <MudButton Variant="@Variant.Filled" Color="Color.Primary" OnClick="() => Activate(panel01)">Item One</MudButton> <MudButton Variant="@Variant.Filled" Color="Color.Primary" OnClick="() => Activate(panel02)" Class="mx-2">Item Two</MudButton> <MudButton Variant="@Variant.Filled" Color="Color.Primary" OnClick="() => Activate(panel03)">Item Three</MudButton> </div> <MudText GutterBottom="true" Align="Align.Center" Class="mt-4"><b>Set Active by TabPanel ID</b></MudText> <div class="d-flex justify-center"> <MudButton Variant="@Variant.Filled" Color="Color.Primary" OnClick='() => Activate("pn_one")'>Item One</MudButton> <MudButton Variant="@Variant.Filled" Color="Color.Primary" OnClick='() => Activate("pn_two")' Class="mx-2">Item Two</MudButton> <MudButton Variant="@Variant.Filled" Color="Color.Primary" OnClick='() => Activate("pn_three")'>Item Three</MudButton> </div>
@code { MudTabs tabs; MudTabPanel panel01; MudTabPanel panel02; MudTabPanel panel03; void Activate(int index) { tabs.ActivatePanel(index); } void Activate(MudTabPanel panel) { tabs.ActivatePanel(panel); } void Activate(object id) { tabs.ActivatePanel(id); } }
Binding Active Panel
Two-way synchronization of the selected panel is possible using bindings.
Active Index: 2
<MudTabs Elevation="0" Outlined="true" @bind-ActivePanelIndex="activeIndex"> <MudTabPanel Text="Item One" ID='"pn_one"'></MudTabPanel> <MudTabPanel Text="Item Two" ID='"pn_two"'></MudTabPanel> <MudTabPanel Text="Item Three" ID='"pn_three"'></MudTabPanel> </MudTabs> <MudText>@($"Active Index: {activeIndex}")</MudText>
@code { int activeIndex = 2; }
Dynamic Tabs
A browser-like tab experience can be enabled, allowing users to dynamically add and close tabs.
The close icon can be hidden by disabling ShowCloseIcon
.
UserTabs index: 1 / DynamicTabs ActivePanelIndex: 1
UserTabs.Count: 3 / DynamicTabs Panels.Count: 3
<MudDynamicTabs @ref="" @bind-ActivePanelIndex="" AddTab="" CloseTab="" AddIconToolTip="Click to add a new tab" CloseIconToolTip="Close tab. All data will be lost" PanelClass="px-4 py-6" Elevation="4" Rounded ApplyEffectsToContainer> @foreach (var tab in UserTabs) { <MudTabPanel ID="@tab.Id" Text="@tab.Label" ShowCloseIcon="@tab.ShowCloseIcon">@tab.Content</MudTabPanel> } </MudDynamicTabs> <MudButton OnClick="">Restore</MudButton> <MudSwitch T="bool" Color="Color.Primary" Value="@_showCloseIcon" ValueChanged="">@($"Show {_closeToggableTab}'s close icon")</MudSwitch> <MudText>UserTabs index: @UserIndex / DynamicTabs ActivePanelIndex: @DynamicTabs.ActivePanelIndex</MudText> <MudText>UserTabs.Count: @UserTabs.Count / DynamicTabs Panels.Count: @DynamicTabs.Panels.Count</MudText>
@code { public class TabView { public string Label { get; set; } public string Content { get; set; } public Guid Id { get; set; } public bool ShowCloseIcon { get; set; } = true; } public MudDynamicTabs DynamicTabs; public List<TabView> UserTabs = new(); public int UserIndex; bool _stateHasChanged; bool _showCloseIcon = false; string _closeToggableTab = "Tab B"; void RestoreUserTabs() { UserTabs.Clear(); UserTabs.Add(new TabView {Id = Guid.NewGuid(), Label = "Tab A", Content = "Tab A content"}); UserTabs.Add(new TabView {Id = Guid.NewGuid(), Label = _closeToggableTab, Content = $"{_closeToggableTab} content", ShowCloseIcon = _showCloseIcon }); UserTabs.Add(new TabView {Id = Guid.NewGuid(), Label = "Tab C", Content = "Tab C content"}); UserIndex = 1; // Start on 2nd tab: "Tab B" _stateHasChanged = true; } protected override void OnInitialized() { base.OnInitialized(); RestoreUserTabs(); } protected override void OnAfterRender(bool firstRender) { base.OnAfterRender(firstRender); if (_stateHasChanged) { _stateHasChanged = false; StateHasChanged(); } } private void ToggleShowCloseIcon(bool show) { var tab = UserTabs?.SingleOrDefault(t => t.Label.Equals(_closeToggableTab)); if (tab is not null) tab.ShowCloseIcon = show; _showCloseIcon = show; } public void AddTab(Guid id) { UserTabs.Add(new TabView {Id = id, Label = "dynamic tab", Content = $"Tab ID: {id}"}); UserIndex = UserTabs.Count - 1; // Automatically switch to the new tab. _stateHasChanged = true; } public void RemoveTab(Guid id) { var tabView = UserTabs.SingleOrDefault((t) => Equals(t.Id, id)); if (tabView is not null) { UserTabs.Remove(tabView); _stateHasChanged = true; } } void AddTabCallback() => AddTab(Guid.NewGuid()); void CloseTabCallback(MudTabPanel panel) => RemoveTab((Guid)panel.ID); }
Advanced Dynamic Tabs
Flexibility in styling can be enhanced using Header
and TabPanelHeader
.
Header positioning is adjustable through HeaderPosition
or TabPanelHeaderPosition
.
<MudTabs @bind-ActivePanelIndex="_index" Border="true" Outlined="true" PanelClass="px-4 py-6" ApplyEffectsToContainer="true"> <ChildContent> @foreach (var item in _tabs) { <MudTabPanel Text="@item.Name" Tag="@item.Id">@item.Content</MudTabPanel> } </ChildContent> <Header> <MudButtonGroup> <MudTooltip Text="Prepend a tab"> <MudIconButton Icon="@Icons.Material.Filled.ChevronLeft" OnClick="@( () => AddTabCallback(false) )" /> </MudTooltip> <MudTooltip Text="Append a tab"> <MudIconButton Icon="@Icons.Material.Filled.ChevronRight" OnClick="@( () => AddTabCallback(true) )" /> </MudTooltip> </MudButtonGroup> </Header> <TabPanelHeader> @if(context.Text.StartsWith("Tab") == false) { <MudTooltip Text="only dynamic tabs can be closed"> <MudIconButton Class="ml-2 pa-1" Color="Color.Error" Icon="@Icons.Material.Filled.Remove" OnClick="(_) => RemoveTab(context)" /> </MudTooltip> } </TabPanelHeader> </MudTabs>
@code { private class TabView { public String Name { get; set; } public String Content { get; set; } public Guid Id { get; set; } } private List<TabView> _tabs = new(); private int _index = 0; private int? _nextIndex = null; private void RemoveTab(MudTabPanel tabPanel) { var tab = _tabs.FirstOrDefault(x => x.Id == (Guid)tabPanel.Tag); if(tab != null) { _tabs.Remove(tab); } } protected override void OnInitialized() { base.OnInitialized(); _tabs.Add(new TabView { Content = "First tab content", Name = "Tab A", Id = Guid.NewGuid() }); _tabs.Add(new TabView { Content = "Second tab content", Name = "Tab B", Id = Guid.NewGuid() }); _tabs.Add(new TabView { Content = "Third tab content", Name = "Tab C", Id = Guid.NewGuid() }); } private void AddTabCallback(Boolean append) { var tabView = new TabView { Name = "Dynamic content", Content = "A new tab", Id = Guid.NewGuid() }; //the tab becomes available after it is rendered. Hence, we can't set the index here if(append == true) { _tabs.Add(tabView); _nextIndex = _tabs.Count - 1; } else { _tabs.Insert(0, tabView); _nextIndex = 0; } } protected override void OnAfterRender(bool firstRender) { if(_nextIndex.HasValue == true) { _index = _nextIndex.Value; _nextIndex = null; StateHasChanged(); } } }