AdaptiveShell.Maui
0.2.3
dotnet add package AdaptiveShell.Maui --version 0.2.3
NuGet\Install-Package AdaptiveShell.Maui -Version 0.2.3
<PackageReference Include="AdaptiveShell.Maui" Version="0.2.3" />
<PackageVersion Include="AdaptiveShell.Maui" Version="0.2.3" />
<PackageReference Include="AdaptiveShell.Maui" />
paket add AdaptiveShell.Maui --version 0.2.3
#r "nuget: AdaptiveShell.Maui, 0.2.3"
#:package AdaptiveShell.Maui@0.2.3
#addin nuget:?package=AdaptiveShell.Maui&version=0.2.3
#tool nuget:?package=AdaptiveShell.Maui&version=0.2.3
AdaptiveShell.Maui
Adaptive shell navigation for .NET MAUI. The navigation chrome adapts to the platform and window size — sidebar on large screens, navigation rail on medium screens, bottom navigation on small screens — with support for navigation groups, per-page icons and accent colors.
Platforms
- Android 6.0 (API 23) or later
- iOS 18 or later
- Mac Catalyst 18 or later
- Windows 10 version 1809 (build 17763) or later
The current Apple target frameworks use the .NET 10 iOS/Mac Catalyst 26.5 bindings. The example keeps ValidateXcodeVersion=false for the separate iPhone Duo/Xcode 27.1 build path; Duo remains outside the automated release gate.
Install
dotnet add package AdaptiveShell.Maui
Usage
Register the handlers in MauiProgram.cs:
using AdaptiveShell.Hosting;
var builder = MauiApp.CreateBuilder();
builder
.UseMauiApp<App>()
.UseAdaptiveShell();
Derive your app shell from AShell and declare navigation items in XAML:
<a:AShell
x:Class="MyApp.AppShell"
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:a="clr-namespace:AdaptiveShell.Controls;assembly=AdaptiveShell"
Title="MyApp">
<a:AShellContent
Title="Home"
Icon="home.svg"
ContentTemplate="{DataTemplate local:MainPage}" />
<a:AShellGroup Title="Media" Icon="folder.svg">
<a:AShellContent
Title="Music"
Icon="star.svg"
ContentTemplate="{DataTemplate local:MusicPage}" />
<a:AShellContent
Title="Photos"
Icon="star.svg"
ContentTemplate="{DataTemplate local:PhotosPage}" />
</a:AShellGroup>
</a:AShell>
AShellContent— a top-level navigation item hosting a page.AShellGroup— groups several items behind one entry (flyout/drawer).FullBleed— lets page content extend under the floating navigation bar; drive it withAdaptiveTriggervisual states to react to window size.
See Example/ExampleAShellApp for a full sample.
On Android, window width determines the navigation layout. The navigation rail and group drawer scroll vertically when their content exceeds the available height. In compact windows, bottom navigation measures its items and scrolls horizontally when their required width exceeds the viewport. Fitting content stays still; changing the number of items does not switch navigation layouts.
Accessibility
AShellItem.AutomationId (falling back to Title) is projected onto the native navigation views on every platform — accessibilityIdentifier on iOS/Mac Catalyst, content-desc on Android, AutomationProperties.AutomationId on Windows — so navigation items have stable identifiers for assistive technologies and UI tests. Group landing-page rows are exposed as landing-<id>.
Testing
Headless navigation-model regressions live in Tests/AdaptiveShell.UnitTests. Run them with dotnet test Tests/AdaptiveShell.UnitTests/AdaptiveShell.UnitTests.csproj; they compile the shared controls directly for net10.0. .github/workflows/unit-tests.yml runs them on private master and the synced public main.
E2E tests live in Tests/AdaptiveShell.UITests. They drive the example app through the accessibility tree via Appium — locators use accessibility identifiers, never screen coordinates. The example pages expose page-home, page-home2, page-music, and page-photos markers so navigation tests verify the actual destination.
Prerequisites:
- Node.js, then
npm i -g appium - Drivers:
appium driver install uiautomator2 xcuitest mac2(macOS) /appium driver install windows(Windows)
Run locally:
# macOS: Android / iOS / Mac Catalyst
Tests/AdaptiveShell.UITests/run-uitest.sh <android|ios|maccatalyst> [compact|wide]
# Windows
Tests/AdaptiveShell.UITests/run-uitest.ps1
Configuration via environment variables: UITEST_PLATFORM, UITEST_FORM (compact|wide|duo), UITEST_APP_PATH, UITEST_DEVICE_NAME, UITEST_DEVICE_UDID, UITEST_APPIUM_URL.
Android overflow coverage uses an opt-in example with 12 top-level items and 18 group children. With Appium running and an Android emulator with a short window height, build and run:
dotnet build Example/ExampleAShellApp/ExampleAShellApp.csproj -f net10.0-android -p:TargetFrameworks=net10.0-android -p:EmbedAssembliesIntoApk=true -p:NavigationOverflowSample=true
UITEST_PLATFORM=android UITEST_FORM=wide UITEST_NAVIGATION_OVERFLOW=1 dotnet test Tests/AdaptiveShell.UITests/AdaptiveShell.UITests.csproj --filter FullyQualifiedName~AndroidNavigationScrollTests
Run the same fixture with UITEST_FORM=compact to verify horizontal overflow while retaining bottom navigation, or use a taller wide window to verify the content fits without scrolling. Rebuild the example without NavigationOverflowSample=true before running the ordinary suite.
DarkModeTests additionally switches the system appearance (adb uimode, simctl ui appearance, Windows registry theme) and verifies the shell stays functional in dark mode; screenshots from both themes land in the report.
Android also reads back native night mode; the locked API29 CI image uses an explicitly enabled privileged emulator shell for the same system service command.
Android theme tests also require Python 3 to verify status-bar foreground and each system navigation key from three original screenshots, native mobile:getSystemBars frames, and stable SystemUI/Launcher accessibility bounds. On the observed API32/33 tablet layouts, an absent system navigation-bar frame is accepted only when the original native Launcher taskbar hierarchy supplies one stable full-width bottom frame and all three actual navigation-key children. The capture temporarily enables all native windows and restores the original setting. Missing evidence or insufficient foreground contrast fails the theme test and report.
LandingPageDarkModeTests keeps the group landing page open through light, dark, and restored light appearance. On Android compact and iOS compact/Duo it checks the page background, both SVG icons and titles from original screenshots and native accessibility bounds, then opens both children, clicks their counters, and returns using the native Back affordance. It also verifies both child backgrounds and the returned landing page backgrounds, icons, and titles from the dark captures. Python 3 is required; missing captures or invisible icons fail the test and report. Sidebar, drawer, and direct-leaf layouts have no dedicated landing page and explicitly skip this test.
CI (.github/workflows/uitest.yml) runs Android (phone + tablet emulator matrix), iOS and Windows on every push/PR. The public full-matrix workflow also runs native Mac Catalyst E2E.
Release & quality gate
Releases are gated on a full E2E matrix that runs on the public repo (EVNII/AdaptiveShell.maui, where GitHub Actions is free) via .github/workflows/release-uitest.yml, triggered on every sync to main:
- iOS 18 (macos-15) / 26 (macos-26) / 27 (xcode-27 preview, experimental) × { iPhone (compact), iPad (wide) } — devices are discovered dynamically from the installed simulator runtimes
- iPhone Duo is excluded from automatic E2E and the release gate; this release does not claim Duo E2E validation.
- Android API 26–36 (Appium UiAutomator2's floor is Android 8.0/API 26; API 23–25 remain compile-level coverage) × { phone, tablet }
- Windows single cell; Mac Catalyst single native cell.
The gate: publish.yml's release-gate job waits for the matrix run matching the tagged commit and blocks the NuGet push unless every required cell is green, including the iOS 27 preview and Mac Catalyst cells. Missing required environment or evidence fails validation; platform-specific test exclusions remain explicit in the complete TRX records.
Screenshots are captured at key steps in every test (Shot(...) in Tests/AdaptiveShell.UITests/BaseTest.cs), uploaded per cell as artifacts, and assembled into a report published to GitHub Pages: https://evnii.github.io/AdaptiveShell.maui/.
License
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0-android36.0 is compatible. net10.0-ios26.5 is compatible. net10.0-maccatalyst26.5 is compatible. net10.0-windows10.0.19041 is compatible. |
-
net10.0-android36.0
- Microsoft.Maui.Controls (>= 10.0.100)
- Xamarin.AndroidX.Fragment.Ktx (>= 1.8.9.3)
- Xamarin.AndroidX.Lifecycle.LiveData (>= 2.11.0.1)
- Xamarin.AndroidX.Lifecycle.Runtime.Ktx (>= 2.11.0.1)
- Xamarin.Google.Android.Material (>= 1.14.0.6)
-
net10.0-ios26.5
- Microsoft.Maui.Controls (>= 10.0.100)
-
net10.0-maccatalyst26.5
- Microsoft.Maui.Controls (>= 10.0.100)
-
net10.0-windows10.0.19041
- Microsoft.Maui.Controls (>= 10.0.100)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
Make Android navigation overflow responsive to measured content and available space: vertically scroll the navigation rail and group drawer, and horizontally scroll compact bottom navigation. Preserve width-based layout selection and keep the selected bottom item visible.