Toast
A service-first toast notification system. Unlike other controls in the library, Toast is invoked entirely from code — no XAML placement or special base class required. Show lightweight, transient messages with auto-dismiss, manual dismiss via IDisposable, queue/stack behavior, spinner, progress bar, and full styling control.
Features
Section titled “Features”- Code-invoked — inject
IToasterand callawait toaster.ShowAsync("text")with no XAML setup required - IDisposable dismiss —
ShowAsyncreturns anIDisposablefor programmatic dismiss - Auto-dismiss — configurable duration (default 3s), or
TimeSpan.Zerofor manual only - Pill or Fill — rounded pill (centered, offset from edges) or full-width bar (flush with edges)
- Top or Bottom — position at top or bottom of screen
- Queue or Stack — one-at-a-time queue (default) or multiple visible stacked toasts
- Spinner — indeterminate loading indicator on left or right
- Progress bar — countdown bar that drains over the duration
- Icon — optional icon image
- Tap action —
ICommand(MAUI) orAction(Blazor) on tap, with optional dismiss-on-tap - Feedback — tactile feedback on show/dismiss (MAUI)
- Accessibility —
SemanticScreenReader.Announce()on show (MAUI),role="alert"(Blazor) - Safe area aware — respects iOS home indicator and status bar
- Styling — background color, text color, border, corner radius
MAUI Usage
Section titled “MAUI Usage”IToaster is registered automatically by UseShinyControls(). Inject it via constructor injection. The toast overlay auto-attaches to the current page on first use — no XAML setup required.
using Shiny.Maui.Controls.Toast;
public class MyViewModel(IToaster toaster){ // Simple toast await toaster.ShowAsync("Item saved!");
// With configuration IDisposable toast = await toaster.ShowAsync("Uploading...", cfg => { cfg.Spinner = ToastSpinnerPosition.Left; cfg.Duration = TimeSpan.Zero; // manual dismiss only cfg.DismissOnTap = false; });
// Dismiss when done toast.Dispose();}Full Configuration Example
Section titled “Full Configuration Example”await toaster.ShowAsync("Connection lost", cfg =>{ cfg.Duration = TimeSpan.FromSeconds(5); cfg.Position = ToastPosition.Bottom; cfg.DisplayMode = ToastDisplayMode.FillHorizontal; cfg.DismissOnTap = true; cfg.QueueMode = ToastQueueMode.Stack; cfg.UseFeedback = true; cfg.ShowProgressBar = true; cfg.BackgroundColor = Colors.Red; cfg.TextColor = Colors.White; cfg.BorderColor = Colors.DarkRed; cfg.BorderThickness = 1; cfg.Icon = ImageSource.FromFile("warning.png"); cfg.TapCommand = new Command(() => NavigateToDetails());});Themed Methods (MAUI)
Section titled “Themed Methods (MAUI)”Convenience methods with preset colors for common notification types:
await toaster.InfoAsync("Update available"); // Blueawait toaster.SuccessAsync("File saved"); // Greenawait toaster.WarningAsync("Storage almost full"); // Amberawait toaster.DangerAsync("Save failed"); // Orangeawait toaster.CriticalAsync("System error"); // Red
// Override after theme defaults are appliedawait toaster.SuccessAsync("Done!", cfg =>{ cfg.Duration = TimeSpan.FromSeconds(5); cfg.ShowProgressBar = true;});Customizing Theme Colors
Section titled “Customizing Theme Colors”Define ToastTypeStyle resources in App.xaml to override the built-in defaults:
<Application.Resources> <shiny:ToastTypeStyle x:Key="ShinyToastSuccessStyle" BackgroundColor="#065F46" TextColor="White" BorderColor="#10B981" /> <shiny:ToastTypeStyle x:Key="ShinyToastCriticalStyle" BackgroundColor="#7F1D1D" TextColor="White" BorderColor="#DC2626" BorderThickness="2" /></Application.Resources>Style keys: ShinyToastInfoStyle, ShinyToastSuccessStyle, ShinyToastWarningStyle, ShinyToastDangerStyle, ShinyToastCriticalStyle
Blazor Usage
Section titled “Blazor Usage”Register the toast service in Program.cs:
using Shiny.Blazor.Controls.Toast;
builder.Services.AddShinyToast();Place <ToastHost /> once in your layout (e.g., MainLayout.razor):
@using Shiny.Blazor.Controls.Toast
<div class="page"> <main>@Body</main></div>
<ToastHost />@inject IToastService ToastService
<button @onclick="ShowToast">Save</button>
@code { async Task ShowToast() { await ToastService.ShowAsync("Saved!", cfg => { cfg.Position = ToastPosition.Bottom; cfg.Duration = TimeSpan.FromSeconds(3); }); }}Themed Methods (Blazor)
Section titled “Themed Methods (Blazor)”await ToastService.InfoAsync("Update available");await ToastService.SuccessAsync("File saved");await ToastService.WarningAsync("Storage almost full");await ToastService.DangerAsync("Save failed");await ToastService.CriticalAsync("System error");Properties
Section titled “Properties”| Property | Type (MAUI / Blazor) | Default | Description |
|---|---|---|---|
Text | string | (required) | Toast message text |
Duration | TimeSpan | 3s | Auto-dismiss duration. TimeSpan.Zero = manual only |
Position | ToastPosition | Bottom | Top or Bottom |
DisplayMode | ToastDisplayMode | Pill | Pill (rounded, offset) or FillHorizontal (flush, full width) |
DismissOnTap | bool | true | Tap to dismiss |
QueueMode | ToastQueueMode | Queue | Queue (one at a time) or Stack (multiple visible) |
Offset | Thickness / double | 12 | Margin from edges (pill mode only) |
Spinner | ToastSpinnerPosition | None | None, Left, or Right |
UseFeedback | bool | true | Feedback on show/dismiss (MAUI only) |
ShowProgressBar | bool | false | Countdown progress bar |
BackgroundColor | Color? / string? | dark gray | Background fill |
TextColor | Color? / string? | white | Text color |
BorderColor | Color? / string? | none | Border stroke |
BorderThickness | double | 0 | Border width |
CornerRadius | double | 20 | Corner radius (pill mode) |
Icon | ImageSource? | null | Optional icon (MAUI) |
IconHtml | string? | null | Optional HTML/SVG icon (Blazor) |
TapCommand | ICommand? | null | Command on tap (MAUI) |
TapCallback | Action? | null | Callback on tap (Blazor) |
AnnounceToScreenReader | bool | true | Screen reader announce (MAUI) |
ViewModel Pattern
Section titled “ViewModel Pattern”public partial class UploadViewModel(IToaster toaster) : ObservableObject{ IDisposable? uploadToast;
[RelayCommand] async Task Upload() { uploadToast = await toaster.ShowAsync("Uploading...", cfg => { cfg.Spinner = ToastSpinnerPosition.Left; cfg.Duration = TimeSpan.Zero; });
await DoUploadAsync(); uploadToast.Dispose();
await toaster.ShowAsync("Upload complete!"); }}AI Skill
Section titled “AI Skill”Step 1 — Add the marketplace:
claude plugin marketplace add shinyorg/skills Step 2 — Install the plugin:
claude plugin install shiny-controls@shiny Step 1 — Add the marketplace:
copilot plugin marketplace add https://github.com/shinyorg/skills Step 2 — Install the plugin:
copilot plugin install shiny-controls@shiny