Sharpnado.Tabs
Pure MAUI and Xamarin.Forms Tabs, including fixed tabs, scrollable tabs, bottom tabs, badge, segmented control, custom tabs, button tabs, bendable tabs...
Install / Use
/learn @roubachof/Sharpnado.TabsREADME
Sharpnado.Tabs for .NET MAUI
<table> <thead> <tr> <th>MAUI sample</th> </tr> </thead> <tbody> <tr> <td><img src="Docs/MAUI/banner.png" width="600" /></td> </tr> </tbody> </table>Get it from NuGet:
| Supported MAUI platforms | |----------------------------| | :heavy_check_mark: Android | | :heavy_check_mark: iOS | | :heavy_check_mark: Windows | | :heavy_check_mark: Mac |
- MAUI version
- Fully customizable
- Underlined tabs, bottom tabs, Segmented control, scrollable tabs
- Pure MAUI touch effects (ripple, standard touch effect) for ALL platforms
- Vertical tabs
- Lazy and Delayed views
- Material tabs specs full implementation
- SVG support thanks to GeometryIcon
- Badge on tabs
- Component oriented architecture
- Layout your tabs and ViewSwitcher as you want
- Bindable
Platform Demonstrations
<table> <thead> <tr> <th>iOS</th> <th>Android</th> <th>Windows</th> <th>MacCatalyst</th> </tr> </thead> <tbody> <tr> <td><img src="Docs/videos/iphone_400.gif" width="190" /></td> <td><img src="Docs/videos/android_400.gif" width="190" /></td> <td><img src="Docs/videos/windows_400.gif" width="190" /></td> <td><img src="Docs/videos/maccatalyst_400.gif" width="190" /></td> </tr> </tbody> </table>What's New in Version 4.0
Pure MAUI Touch Effects
Version 4.0 introduces new touch effect properties that work across all platforms without custom handlers:
- TouchEffectType: Choose from
CircularRipple,Standard, orPoorsManRipple - TouchColor: Set the color of the touch effect
Examples:
CircularRipple Effect:
<tabs:TabHostView TouchColor="{StaticResource Primary}"
TouchEffectType="CircularRipple">
<tabs:MaterialUnderlinedTabItem Label="Tab 1" />
<tabs:MaterialUnderlinedTabItem Label="Tab 2" />
</tabs:TabHostView>
Standard Touch Effect:
<tabs:TabHostView TouchColor="{StaticResource Secondary}"
TouchEffectType="Standard">
<tabs:MaterialUnderlinedTabItem Label="Tab 1" />
<tabs:MaterialUnderlinedTabItem Label="Tab 2" />
</tabs:TabHostView>
PoorsManRipple Effect:
<tabs:TabHostView TouchColor="BlueViolet"
TouchEffectType="PoorsManRipple">
<tabs:MaterialUnderlinedTabItem Label="Tab 1" />
<tabs:MaterialUnderlinedTabItem Label="Tab 2" />
</tabs:TabHostView>
Live Examples: See these effects in action in the sample project:
- TabM.xaml - CircularRipple and Standard effects
- TabA.xaml - Standard and PoorsManRipple effects
- TabU.xaml - CircularRipple effect with SelectedIconSource
Other Improvements
- Enhanced platform support: Full MacCatalyst and Windows support
- Improved performance: Better SelectedItem handling and scroll-to-selected functionality
- Touch gesture updates: Modern MAUI gesture handling for better stability
- SelectedIconSource: Display different icons for selected/unselected states
Installation
MAUI Setup
In your MauiProgram.cs, add the Sharpnado.Tabs initialization:
public static class MauiProgram
{
public static MauiApp CreateMauiApp()
{
var builder = MauiApp.CreateBuilder();
builder
.UseMauiApp<App>()
.UseSharpnadoTabs(loggerEnable: false);
return builder.Build();
}
}
Features Showcase
<table> <thead> <tr> <th>Bottom bar tabs</th> <th>Fixed tabs</th> <th>Scrollable tabs</th> </tr> </thead> <tbody> <tr> <td><img src="Docs/ios_bottom_tabs.gif" width="250" /></td> <td><img src="Docs/android_fixed_tabs.gif" width="250" /></td> <td><img src="Docs/ios_scrollable_tabs.gif" width="250" /></td> </tr> <tr> <td>BottomTabItem</td> <td>UnderlinedTabItem</td> <td>TabType.Scrollable</td> </tr> </tbody> </table> <table> <thead> <tr> <th>Segmented tabs</th> <th>Custom tabs</th> </tr> </thead> <tbody> <tr> <td><img src="Docs/android_segmented_light_carrel.png" width="300" /></td> <td><img src="Docs/android_spam_tabs.gif" width="300" /></td> </tr> <tr> <td>Neumorphic design</td> <td>inherit from TabItem</td> </tr> </tbody> </table> <table> <thead> <tr> <th>Material top icon</th> <th>Material leading icon</th> </tr> </thead> <tbody> <tr> <td><img src="Docs/top_icon.png" width="300" /></td> <td><img src="Docs/leading_icon.png" width="300" /></td> </tr> <tr> <td>IconOptions="TopIcon"</td> <td>IconOptions="LeadingIcon"</td> </tr> </tbody> </table> <table> <thead> <tr> <th>BadgeView</th> <th>BadgeView (Chips)</th> </tr> </thead> <tbody> <tr> <td><img src="Docs/bottom_tabs_uwp.png" width="300" /></td> <td><img src="Docs/underlined_tabs_droid.png" width="300" /></td> </tr> <tr> <td>Numbers, Indicator</td> <td>Chips with text</td> </tr> </tbody> </table> <table> <thead> <tr> <th>Vertical Tabs</th> </tr> </thead> <tbody> <tr> <td><img src="Docs/vertical_tabs.png" width="600" /></td> </tr> <tr> <td>Orientation="Vertical"</td> </tr> </tbody> </table>Getting Started
Basic Usage
The core concept is to separate your tabs (TabHostView) from your content (ViewSwitcher). They communicate through the SelectedIndex property:
<tabs:TabHostView SelectedIndex="{Binding SelectedViewModelIndex, Mode=TwoWay}">
<tabs:UnderlinedTabItem Label="Tab 1" />
<tabs:UnderlinedTabItem Label="Tab 2" />
<tabs:UnderlinedTabItem Label="Tab 3" />
</tabs:TabHostView>
<tabs:ViewSwitcher SelectedIndex="{Binding SelectedViewModelIndex, Mode=TwoWay}">
<views:View1 />
<views:View2 />
<views:View3 />
</tabs:ViewSwitcher>
Features
Material tabs
Contributor: @mkanyo (Miklos Kanyo)
Since version 2.2, a new type of tab has been introduced: the MaterialUnderlinedTabItem.
It's a full implementation of the material tabs specifications:
https://material.io/components/tabs

IconOptions values:
- TopIcon
- IconOnly
- LeadingIcon
- TextOnly
You can also set precisely the gap between the icon and the text thanks to the IconTextSpacing.
Instead of using a classic Image you can also set a svg Geometry (SVG image) icon thanks to the GeometryIcon property.
Cool Hack: you can use MaterialUnderlinedTabItem (and then use a SVG image) as a bottom bar item, just specify UnderlineHeight = 0.
If you chose to go down this road you can also set the following properties:
public bool Fillpublic double StrokeThicknesspublic double IconTextSpacing
<tabs:TabHostView x:Name="TabHost"
Grid.Row="4"
Style="{DynamicResource DynamicBottomShadow}"
Margin="-16,0"
BackgroundColor="{DynamicResource Elevation4dpColor}"
ShowScrollbar="False"
TabType="Scrollable"
SelectedIndex="{Binding Source={x:Reference Switcher}, Path=SelectedIndex, Mode=TwoWay}">
<tabs:TabHostView.Tabs>
<tabs:MaterialUnderlinedTabItem Style="{StaticResource ScrollableTabStyle}"
IconImageSource="list_96.png"
IconOptions="TopIcon"
IconSize="24"
IconTextSpacing="0"
Label="{localization:Translate Tabs_Quote}"
UnderlineHeight="2" />
<tabs:MaterialUnderlinedTabItem Style="{StaticResource ScrollableTabStyle}"
IconImageSource="theme_96.png"
IconOptions="IconOnly"
IconSize="24"
IconTextSpacing="0"
Label="FILMO" />
<tabs:MaterialUnderlinedTabItem Style="{StaticResource ScrollableTabStyle}"
IconImageSource="grid_view_96.png"
IconOptions="LeadingIcon"
IconSize="24"
IconTextSpacing="0"
Label="{localization:Translate Tabs_Meme}" />
<tabs:MaterialUnderlinedTabItem Style="{StaticResource ScrollableTabStyle}"
Padding="10,0"
IconImageSource="house_96.png"
IconOptions="TextOnly"
IconSize="24"
IconTextSpacing="0"
Label="NONSENSE" />
</tabs:TabHostView.Tabs>
</tabs:TabHostView>
UnderlinedTabItem
Let's consider this view:
<p align="center"> <img src="Docs/android_fixed_tabs.gif" width="250" /> </p>And let's have a look at its code:
<Grid Padding="{StaticResource StandardThickness}"
ColumnSpacing="0"
RowSpacing="0">
<Grid.RowDefinitions>
<RowDefinition Height="200" />
<RowDefinition Height="40" />
<RowDefinition Height="30" />
<RowDefinition Height="30" />
<RowDefinition Height="50" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<!-- first 4
Related Skills
node-connect
339.5kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
frontend-design
83.9kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
openai-whisper-api
339.5kTranscribe audio via OpenAI Audio Transcriptions API (Whisper).
commit-push-pr
83.9kCommit, push, and open a PR
