Theming
Theme tokens, light and dark mode, and your own colours.
Every component takes its colours from theme tokens that mirror ShellUI's CSS variables (--background, --primary, --border, …). ShellTheme, in the Shell.cs that init installs, holds a light and a dark palette and publishes the active one as application resources, so switching theme repaints every component.
Tokens
| Token | Used for |
|---|---|
Background / Foreground |
Page and dialog surface, body text |
Card / CardForeground |
Card surface |
Popover / PopoverForeground |
Dropdown, popover and select panels |
Primary / PrimaryForeground |
Default button, checked checkbox / switch / radio, progress fill |
Secondary, Muted, Accent (+ *Foreground) |
Secondary button, tab list, skeleton, hover backgrounds |
Destructive, Success, Warning, Info (+ *Foreground) |
Status variants: badge, alert, progress, labels |
Border, Input, Ring |
Dividers, field borders, the focus ring |
Overlay |
Dialog, drawer and sheet backdrop |
Chart1 … Chart5 |
Chart series, in order (ShellUI's --chart-1 … --chart-5). |
Using tokens in your XAML
Each token is published as a colour, ShellUI<Token>, and a brush, ShellUI<Token>Brush:
<ContentPage BackgroundColor="{DynamicResource ShellUIBackground}">
<Label Text="Muted text" TextColor="{DynamicResource ShellUIMutedForeground}" />
<Border Stroke="{DynamicResource ShellUIBorderBrush}" />
</ContentPage>
<Window Background="{DynamicResource ShellUIBackgroundBrush}">
<TextBlock Text="Muted text" Foreground="{DynamicResource ShellUIMutedForegroundBrush}" />
<Border BorderBrush="{DynamicResource ShellUIBorderBrush}" BorderThickness="1" />
</Window>
In code, the Token extension binds a colour or brush property to a token, and keeps it in step when the theme changes:
myBorder.Token(Border.StrokeProperty, ShellToken.Border);
myBorder.Token(Border.BorderBrushProperty, ShellToken.Border);
Light and dark
The theme follows the operating system until you pick one. Switch it from code, or drop a Theme Toggle on the page:
ShellTheme.SetTheme(AppTheme.Dark);
ShellTheme.ToggleTheme();
ShellTheme.SetTheme(ThemeVariant.Dark);
ShellTheme.ToggleTheme();
ShellTheme.ThemeChanged fires after every switch, and ShellTheme.IsDarkMode tells you which palette is active.
Your own colours
Change tokens before the first page loads, then publish them again:
ShellTheme.Light[ShellToken.Primary] = Color.FromArgb("#2563EB");
ShellTheme.Dark[ShellToken.Primary] = Color.FromArgb("#3B82F6");
ShellTheme.Apply();
ShellTheme.Light[ShellToken.Primary] = Color.Parse("#2563EB");
ShellTheme.Dark[ShellToken.Primary] = Color.Parse("#3B82F6");
ShellTheme.Apply();
Since Shell.cs is your code, you can also edit the palettes there directly.
Android system bars
On MAUI, set ShellTheme.SyncSystemBars = true before EnsureInitialized() to make Android's status and navigation bars follow the theme: the bars turn transparent over the page, their icons flip with light and dark, and dialog backdrops cover them. Also set colorPrimary and colorPrimaryDark in Platforms/Android/Resources/values/colors.xml to your background colour, so the splash screen doesn't flash the template's purple.