Toast
Transient, non-blocking notification messages that appear temporarily and auto-dismiss. Display confirmations, errors, warnings, or status updates without interrupting the user's workflow. Style toasts freely with Tailwind CSS classes.
Overview
The MToast component provides a clean, accessible way to display temporary notifications.
It features nine flexible placement positions, configurable duration, and automatic FIFO (First-In-First-Out) dismissal.
The toast system is backed by MToastService, allowing you to trigger notifications from anywhere in your application.
Visual appearance is entirely up to you — pass any Tailwind CSS classes via the class parameter on Show().
Key Features:
- Nine placement options (all corners, centers, and edges)
- Fully class-driven styling — pass any Tailwind CSS classes
- Auto-dismissal with configurable duration
- FIFO queue management (removes oldest toast first)
- Portals to
document.body— always renders above all content
Usage
Add the namespace imports and register the service in your Program.cs:
// Program.cs
builder.Services.AddMaraiUI();
@using Marai.UI.Components.MToast
@inject MToastService ToastServiceAdd the Toaster in App.razor:
<MToaster />Basic Usage
Place <MToaster /> once in your root layout (e.g., MainLayout.razor or App.razor).
Then inject MToastService anywhere you need to show notifications:
@inject MToastService ToastService
<MButton OnClick="ShowToast">Show Toast</MButton>
@code {
private void ShowToast()
=> ToastService.Show("Your changes have been saved successfully.");
}
Examples
Styling with Tailwind Classes
Pass any Tailwind CSS classes via the class parameter to control each toast's appearance.
This gives you complete control over background color, text color, padding, width, border radius, and shadow.
@inject MToastService ToastService
<div style="display:flex;gap:0.5rem;flex-wrap:wrap;">
<MButton Class="inline-flex items-center justify-center rounded-md bg-blue-600 px-4 py-2 text-sm font-medium text-white hover:bg-blue-700" OnClick='@(() => ToastService.Show("Primary notification message", "w-80 p-4 bg-blue-600 text-white rounded-lg shadow-lg"))'>Blue</MButton>
<MButton Class="inline-flex items-center justify-center rounded-md bg-slate-500 px-4 py-2 text-sm font-medium text-white hover:bg-slate-600" OnClick='@(() => ToastService.Show("Secondary information", "w-80 p-4 bg-slate-500 text-white rounded-lg shadow-lg"))'>Slate</MButton>
<MButton Class="inline-flex items-center justify-center rounded-md bg-emerald-600 px-4 py-2 text-sm font-medium text-white hover:bg-emerald-700" OnClick='@(() => ToastService.Show("Operation completed successfully!", "w-80 p-4 bg-emerald-600 text-white rounded-lg shadow-lg"))'>Emerald</MButton>
<MButton Class="inline-flex items-center justify-center rounded-md bg-red-600 px-4 py-2 text-sm font-medium text-white hover:bg-red-700" OnClick='@(() => ToastService.Show("Error: Something went wrong", "w-80 p-4 bg-red-600 text-white rounded-lg shadow-lg"))'>Red</MButton>
<MButton Class="inline-flex items-center justify-center rounded-md bg-amber-500 px-4 py-2 text-sm font-medium text-white hover:bg-amber-600" OnClick='@(() => ToastService.Show("Warning: Action requires attention", "w-80 p-4 bg-amber-500 text-white rounded-lg shadow-lg"))'>Amber</MButton>
<MButton Class="inline-flex items-center justify-center rounded-md bg-sky-500 px-4 py-2 text-sm font-medium text-white hover:bg-sky-600" OnClick='@(() => ToastService.Show("Information: Background sync in progress", "w-80 p-4 bg-sky-500 text-white rounded-lg shadow-lg"))'>Sky</MButton>
</div>
Placement Options
Control where each toast appears by passing a placement parameter to Show().
Nine positions are available. Each call can target a different position independently.
@inject MToastService ToastService
<div style="display:grid;grid-template-columns:repeat(3,1fr);gap:0.5rem;max-width:600px;">
<MButton Class="inline-flex items-center justify-center rounded-md bg-slate-900 px-3 py-1.5 text-sm font-medium text-white hover:bg-slate-800" OnClick="@(() => ShowToastAt(ToastPlacement.TopLeft))">Top Left</MButton>
<MButton Class="inline-flex items-center justify-center rounded-md bg-slate-900 px-3 py-1.5 text-sm font-medium text-white hover:bg-slate-800" OnClick="@(() => ShowToastAt(ToastPlacement.TopCenter))">Top Center</MButton>
<MButton Class="inline-flex items-center justify-center rounded-md bg-slate-900 px-3 py-1.5 text-sm font-medium text-white hover:bg-slate-800" OnClick="@(() => ShowToastAt(ToastPlacement.TopRight))">Top Right</MButton>
<MButton Class="inline-flex items-center justify-center rounded-md bg-slate-900 px-3 py-1.5 text-sm font-medium text-white hover:bg-slate-800" OnClick="@(() => ShowToastAt(ToastPlacement.MiddleLeft))">Middle Left</MButton>
<MButton Class="inline-flex items-center justify-center rounded-md bg-slate-900 px-3 py-1.5 text-sm font-medium text-white hover:bg-slate-800" OnClick="@(() => ShowToastAt(ToastPlacement.MiddleCenter))">Middle Center</MButton>
<MButton Class="inline-flex items-center justify-center rounded-md bg-slate-900 px-3 py-1.5 text-sm font-medium text-white hover:bg-slate-800" OnClick="@(() => ShowToastAt(ToastPlacement.MiddleRight))">Middle Right</MButton>
<MButton Class="inline-flex items-center justify-center rounded-md bg-slate-900 px-3 py-1.5 text-sm font-medium text-white hover:bg-slate-800" OnClick="@(() => ShowToastAt(ToastPlacement.BottomLeft))">Bottom Left</MButton>
<MButton Class="inline-flex items-center justify-center rounded-md bg-slate-900 px-3 py-1.5 text-sm font-medium text-white hover:bg-slate-800" OnClick="@(() => ShowToastAt(ToastPlacement.BottomCenter))">Bottom Center</MButton>
<MButton Class="inline-flex items-center justify-center rounded-md bg-slate-900 px-3 py-1.5 text-sm font-medium text-white hover:bg-slate-800" OnClick="@(() => ShowToastAt(ToastPlacement.BottomRight))">Bottom Right</MButton>
</div>
@code {
private void ShowToastAt(ToastPlacement placement)
=> ToastService.Show($"Toast at {placement}", "w-80 p-4 bg-slate-800 text-white rounded-lg shadow-lg", 3000, placement);
}
Dark and Light Themes
Because toasts are styled entirely with Tailwind classes, any visual theme is achievable.
Use bg-slate-900 text-slate-50 for dark toasts, bg-white text-slate-800 border for light ones.
Pass a Class to <MToaster /> as a default fallback for toasts that don't specify their own class.
@inject MToastService ToastService
<div style="display:flex;gap:0.5rem;flex-wrap:wrap;">
<MButton Class="inline-flex items-center justify-center rounded-md bg-slate-900 px-4 py-2 text-sm font-medium text-white hover:bg-slate-800" OnClick="ShowDark">Dark Toast</MButton>
<MButton Class="inline-flex items-center justify-center rounded-md border border-slate-300 bg-white px-4 py-2 text-sm font-medium text-slate-700 hover:bg-slate-50" OnClick="ShowLight">Light Toast</MButton>
</div>
@code {
private void ShowDark()
=> ToastService.Show("Dark themed notification", "w-80 p-4 bg-slate-900 text-slate-50 border border-slate-700 rounded-lg shadow-xl", 3000);
private void ShowLight()
=> ToastService.Show("Light themed notification", "w-80 p-4 bg-white text-slate-800 border border-slate-200 rounded-lg shadow-lg", 3000);
}
Custom Duration
Set a custom duration in milliseconds. Pass 0 to create a persistent toast that remains until manually dismissed.
@inject MToastService ToastService
<div style="display:flex;gap:0.5rem;flex-wrap:wrap;">
<MButton Class="inline-flex items-center justify-center rounded-md bg-slate-900 px-4 py-2 text-sm font-medium text-white hover:bg-slate-800" OnClick='@(() => ToastService.Show("Quick message (2s)", "w-80 p-4 bg-slate-800 text-white rounded-lg shadow-lg", 2000))'>2 Seconds</MButton>
<MButton Class="inline-flex items-center justify-center rounded-md bg-slate-900 px-4 py-2 text-sm font-medium text-white hover:bg-slate-800" OnClick='@(() => ToastService.Show("Standard message (5s)", "w-80 p-4 bg-slate-800 text-white rounded-lg shadow-lg", 5000))'>5 Seconds (Default)</MButton>
<MButton Class="inline-flex items-center justify-center rounded-md bg-slate-900 px-4 py-2 text-sm font-medium text-white hover:bg-slate-800" OnClick='@(() => ToastService.Show("Longer message (10s)", "w-80 p-4 bg-slate-800 text-white rounded-lg shadow-lg", 10000))'>10 Seconds</MButton>
<MButton Class="inline-flex items-center justify-center rounded-md border border-slate-300 bg-white px-4 py-2 text-sm font-medium text-slate-700 hover:bg-slate-50" OnClick='@(() => ToastService.Show("This stays until dismissed", "w-80 p-4 bg-amber-500 text-white rounded-lg shadow-lg", 0))'>Persistent (0)</MButton>
</div>
Sizing
Control toast width and padding using Tailwind utilities in the class parameter passed to Show().
@inject MToastService ToastService
<div style="display:flex;gap:0.5rem;flex-wrap:wrap;align-items:center;">
<MButton Class="inline-flex items-center justify-center rounded-md bg-slate-900 px-3 py-1.5 text-sm font-medium text-white hover:bg-slate-800" OnClick='@(() => ToastService.Show("Compact toast", "w-60 p-2 text-xs bg-slate-800 text-white rounded shadow-md", 3000))'>Compact</MButton>
<MButton Class="inline-flex items-center justify-center rounded-md bg-slate-900 px-4 py-2 text-sm font-medium text-white hover:bg-slate-800" OnClick='@(() => ToastService.Show("Default toast notification", "w-80 p-4 bg-slate-800 text-white rounded-lg shadow-lg", 3000))'>Default</MButton>
<MButton Class="inline-flex items-center justify-center rounded-md bg-slate-900 px-4 py-2 text-sm font-medium text-white hover:bg-slate-800" OnClick='@(() => ToastService.Show("Wide toast notification with more space", "w-96 p-4 bg-slate-800 text-white rounded-xl shadow-xl", 3000))'>Wide</MButton>
</div>
Multiple Toasts
Each call to Show() adds a new toast to the stack. They auto-dismiss independently using FIFO order
(First-In-First-Out — oldest toast is removed first when duration expires).
@inject MToastService ToastService
<MButton Class="inline-flex items-center justify-center rounded-md bg-slate-900 px-4 py-2 text-sm font-medium text-white hover:bg-slate-800" OnClick="ShowMultiple">Show Multiple Toasts</MButton>
@code {
private void ShowMultiple()
{
ToastService.Show("First notification", "w-80 p-4 bg-sky-600 text-white rounded-lg shadow-lg", 4000);
Task.Delay(500).ContinueWith(_ => ToastService.Show("Second notification", "w-80 p-4 bg-emerald-600 text-white rounded-lg shadow-lg", 4000));
Task.Delay(1000).ContinueWith(_ => ToastService.Show("Third notification", "w-80 p-4 bg-amber-500 text-white rounded-lg shadow-lg", 4000));
}
}
Accessibility
- Normal toasts render with
role="status"— screen readers announce the message politely without interrupting the user - Alert toasts (errors, destructive actions) render with
role="alert"— screen readers announce the message assertively and immediately - The dismiss button includes
aria-label="Dismiss notification"and is always keyboard reachable - The dismiss icon carries
aria-hidden="true"— the accessible label comes from the button itself - Focus is never moved automatically to a toast — toasts are non-blocking and do not interrupt the current workflow
Use ShowAlert() for errors, payment failures, destructive confirmations, or any message that must be read immediately:
// Normal — announced politely
ToastService.Show("Report exported successfully.", "bg-slate-900 text-white ...");
// Alert — announced immediately
ToastService.ShowAlert("Payment failed. Please check your card details.", "bg-red-600 text-white ...");API Reference
MToastService
| Member | Type | Description |
|---|---|---|
| Toasts | IReadOnlyList<MToastItem> | Snapshot of all currently active toasts. |
| OnChanged | Action? | Fires whenever the toast list changes (add or remove). |
| Show(message, class, duration, placement) | void |
Adds a new toast. class is an optional Tailwind CSS string applied to the toast element.
duration defaults to 5000 ms; pass 0 to disable auto-dismiss.
placement defaults to ToastPlacement.BottomRight.
|
| Dismiss(id) | void | Removes the toast with the given Guid id. |
MToaster
| Parameter | Type | Default | Description |
|---|---|---|---|
| Class | string? | null |
Default CSS classes applied to all toasts. Overridden when a per-toast class is passed to Show(). |
MToast
| Parameter | Type | Default | Description |
|---|---|---|---|
| Item | MToastItem | required | The toast data record to render. |
| OnDismiss | EventCallback | — | Invoked when the close button is clicked. |
| Class | string? | null |
CSS classes applied to this toast element. Falls back to MToaster.Class when not set. |
| AdditionalAttributes | Dictionary<string, object>? | null |
Arbitrary HTML attributes passed through to the toast element. |
MToastItem
| Property | Type | Description |
|---|---|---|
| Id | Guid | Unique identifier assigned on creation. |
| Message | string | Text content of the notification. |
| Class | string? | Optional Tailwind CSS classes controlling this toast's visual appearance. |
| Duration | int | Auto-dismiss delay in milliseconds. 0 = persistent. |
| Placement | ToastPlacement | Screen position for this toast. Defaults to BottomRight. |
ToastPlacement Enum
| Value | Position | Best Used For |
|---|---|---|
TopLeft |
Top-left corner | System notifications, background updates |
TopCenter |
Top-center of screen | Important alerts that need immediate attention |
TopRight |
Top-right corner | Non-intrusive notifications |
BottomLeft |
Bottom-left corner | Status updates, progress notifications |
BottomCenter |
Bottom-center of screen | Cookie consents, temporary messages |
BottomRight |
Bottom-right corner (default) | Standard notifications, success messages |
MiddleLeft |
Middle-left edge | Side navigation notifications |
MiddleCenter |
Center of screen | Critical warnings, modal-like alerts |
MiddleRight |
Middle-right edge | Contextual notifications related to sidebar content |
Register the service in Program.cs with builder.Services.AddMaraiUI(),
then place <MToaster /> once in your root layout. The component subscribes to
MToastService automatically and renders all active toasts.
When multiple toasts are active and a duration expires, the oldest toast is removed first (First-In-First-Out). This ensures that users see messages in the order they were triggered, preventing confusion when multiple notifications appear rapidly.
MToaster moves its container to document.body on first render,
bypassing any CSS stacking context from ancestor elements. This guarantees toasts remain
visible above modals, overlays, and other fixed-position content.