Shell & App-Wide Flyouts
ShinyFlyout is a pair of attached properties — StartTemplate and EndTemplate — that install a flyout over every page a host shows. Put them on a Shell, a NavigationPage, or a single page.
<Shell xmlns="http://schemas.microsoft.com/dotnet/2021/maui" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:shiny="http://shiny.net/maui/controls" x:Class="MyApp.AppShell" FlyoutBehavior="Disabled">
<shiny:ShinyFlyout.StartTemplate> <DataTemplate> <shiny:FlyoutPanel State="Hidden" CollapsedState="Hidden" Presentation="Overlay" ExpandedWidth="280"> <shiny:FlyoutPanel.HeaderContent> <Label Text="Menu" FontSize="18" FontAttributes="Bold" Padding="20,18" /> </shiny:FlyoutPanel.HeaderContent>
<VerticalStackLayout Padding="8"> <Label Text="Home" Padding="16,12" /> <Label Text="Projects" Padding="16,12" /> <Label Text="Settings" Padding="16,12" /> </VerticalStackLayout> </shiny:FlyoutPanel> </DataTemplate> </shiny:ShinyFlyout.StartTemplate>
<!-- ShellContent … --></Shell>Open it from anywhere with IFlyoutService:
public class ToolbarViewModel(IFlyoutService flyouts){ public Task OpenMenu() => flyouts.ToggleAsync();}Why it is a template
Section titled “Why it is a template”Each page builds its own panel from the template. Sharing one panel instance across pages would mean re-parenting it on every navigation, which rebuilds its native views and throws away scroll position and focus.
What carries across pages is the state — a drawer left open is still open on the page you land on, and a rail stays a rail.
Shell specifics
Section titled “Shell specifics”- Set
Shell.FlyoutBehavior="Disabled"so Shell’s own drawer stays out of the way. - The flyout wraps the page’s content, so a panel sits below the nav bar and above the tab bar, and
Presentation="Push"pushes the page content rather than Shell’s chrome. AddShell.NavBarIsVisible="False"to a page if the panel should run the full height of the window. - A page that is already a
ShinyFlyoutPageis skipped — it brings its own.
NavigationPage
Section titled “NavigationPage”The same two properties work on a NavigationPage, which is the closest thing to the old FlyoutPage + Detail = new NavigationPage(...) arrangement:
var nav = new NavigationPage(new HomePage());ShinyFlyout.SetStartTemplate(nav, new DataTemplate(() => new FlyoutPanel{ State = FlyoutPanelState.Hidden, CollapsedState = FlyoutPanelState.Hidden, Presentation = FlyoutPresentation.Overlay, PanelContent = new NavigationMenu()}));Every page pushed onto that stack gets the drawer.
On a single page
Section titled “On a single page”Setting the attached property directly on a ContentPage installs the flyout on just that page — useful when one screen needs a drawer and the rest of the app does not, without changing the page’s base class.
Because XAML applies properties in document order, a template declared above the page’s content is set while the page still has none; the install waits for the content to arrive rather than wrapping nothing.


