Toast
Component

Toast

A succinct message that is displayed temporarily. Toasts are auto-dismissible and should not interrupt the user.

Demo

Features

  • Generic content type - define your own toast structure
  • Auto-close with configurable duration (minimum 5s for accessibility)
  • Pause on hover and focus for user control
  • WCAG compliant with aria-live announcements
  • DI-based queue - inject and use anywhere
  • Template-based rendering - full control over toast appearance
  • Swipe-to-dismiss with configurable direction and threshold
  • Portal to body - avoids CSS stacking context issues
  • Keyboard shortcut (hotkey) to focus toast region

Installation

bash
dotnet add package SummitUI

Quick Start

Get toasts working in 3 steps:

1. Define your toast content type

csharp
// Define your toast content type - can be anything you want
public record MyToast(string Title, string? Description = null);

2. Register in Program.cs

csharp
// In Program.cs
builder.Services.AddSummitUI();
builder.Services.AddToastQueue<MyToast>();

3. Add ToastRegion to your layout and inject the queue

razor
@* In your layout - ToastRegion automatically portals to body *@
<ToastRegion TContent="MyToast" 
             AriaLabel="Notifications"
             GetAnnouncementText="t => t.Description ?? t.Title"
             Hotkey="@(["F8"])"
             class="absolute inset-0 overflow-clip flex flex-col-reverse items-end gap-2 p-4 z-50">
    <ToastTemplate Context="toast">
        <Toast TContent="MyToast" 
               ToastData="toast" 
               SwipeDirection="SwipeDirection.Right"
               SwipeThreshold="50"
               class="bg-slate-800 text-white p-4 rounded-lg max-w-[420px]">
            <span class="font-semibold">@toast.Content.Title</span>
            @if (toast.Content.Description is not null)
            {
                <p class="text-sm opacity-80">@toast.Content.Description</p>
            }
            <ToastCloseButton aria-label="Close">×</ToastCloseButton>
        </Toast>
    </ToastTemplate>
</ToastRegion>

@* In any component *@
@inject IToastQueue<MyToast> Toasts

<button @onclick="() => Toasts.Add(new(\"Saved!\"))">Save</button>

Anatomy

The toast system consists of these components:

razor
ToastRegion (ARIA landmark, portals to body by default)
├── ToastTemplate (RenderFragment<QueuedToast<TContent>>)
│   └── Toast (role="alertdialog", swipe-to-dismiss support)
│       ├── [Your content markup]
│       └── ToastCloseButton
└── Aria-live regions (polite + assertive for screen readers)

Components

ToastRegion<TContent>

ARIA landmark region that contains all toasts. Automatically portals to body to avoid CSS stacking context issues.

Toast<TContent>

Individual toast with role="alertdialog". Supports swipe-to-dismiss with configurable direction.

ToastCloseButton

A button that closes the parent toast. Uses cascading values to find the toast key.

IToastQueue<TContent>

The queue interface. Inject this to add toasts from anywhere in your app.

API Reference

IToastQueue<TContent>

Method Returns Description
Add(content, options?) string Add a toast to the queue. Returns a key for programmatic dismissal.
Close(key) void Close a specific toast by its key.
CloseAll() void Close all toasts immediately.
PauseAll() void Pause all auto-dismiss timers.
ResumeAll() void Resume all auto-dismiss timers.
Subscribe(callback) Action Subscribe to queue changes. Returns unsubscribe function.

ToastOptions

Property Type Default Description
Timeout int? null Auto-dismiss timeout in milliseconds. Minimum 5000ms enforced. Null means no auto-dismiss.
Priority ToastPriority Polite Screen reader announcement priority. Polite or Assertive.
OnClose Action? null Callback when the toast is closed (by user or timeout).

ToastRegion<TContent>

Property Type Default Description
AriaLabel string? null Accessible label for the toast region. Should be localized.
ToastTemplate RenderFragment<QueuedToast<TContent>> null Template for rendering each toast.
GetAnnouncementText Func<TContent, string>? null Function to get screen reader announcement text from toast content.
Hotkey string[]? null Keyboard shortcut to focus the toast region (e.g., ["F8"] or ["altKey", "KeyT"]).
UsePortal bool true Whether to render in a portal appended to body. Avoids CSS stacking context issues.

Toast<TContent>

Property Type Default Description
ToastData QueuedToast<TContent> Required The queued toast data including key and user-defined content.
SwipeDirection SwipeDirection? null Direction to swipe for dismissal (Left, Right, Up, Down). Null disables swipe.
SwipeThreshold int 50 Distance in pixels required to trigger swipe dismissal.

Examples

Simple Toast

razor
@inject IToastQueue<MyToast> Toasts

<button @onclick="() => Toasts.Add(new(\"Hello!\"))">
    Show Toast
</button>

With Timeout

csharp
// Auto-dismiss after 8 seconds
Toasts.Add(
    new("Upload complete"),
    new ToastOptions { Timeout = 8000 }
);

Swipe to Dismiss

razor
@* Enable swipe-to-dismiss on the Toast component *@
<Toast TContent="MyToast" 
       ToastData="toast"
       SwipeDirection="SwipeDirection.Right"
       SwipeThreshold="50"
       class="... data-[swipe=move]:transition-none 
              data-[swipe=move]:translate-x-[var(--summit-toast-swipe-move-x)]
              data-[swipe=end]:animate-out data-[swipe=end]:slide-out-to-right-full">
    ...
</Toast>

@* Swipe directions available: Left, Right, Up, Down *@
@* CSS variables set during swipe: *@
@* --summit-toast-swipe-move-x (horizontal movement) *@
@* --summit-toast-swipe-move-y (vertical movement) *@

Programmatic Dismissal

csharp
string? processingKey;

void StartProcessing()
{
    processingKey = Toasts.Add(
        new("Processing..."),
        new ToastOptions { OnClose = () => processingKey = null }
    );
}

void CancelProcessing()
{
    if (processingKey is not null)
    {
        Toasts.Close(processingKey);
    }
}

Custom Extension Methods

csharp
// Create extension methods for common patterns
public static class MyToastExtensions
{
    public static string Success(this IToastQueue<MyToast> queue, string message)
        => queue.Add(new(message) { Variant = "success" });

    public static string Error(this IToastQueue<MyToast> queue, string message)
        => queue.Add(new(message) { Variant = "error" },
            new() { Priority = ToastPriority.Assertive });
}

// Usage
Toasts.Success("File saved!");
Toasts.Error("Upload failed");

Accessibility

  • ARIA Landmark: ToastRegion renders as role="region" for screen reader navigation.
  • Alert Dialog: Each toast has role="alertdialog" for proper screen reader announcements.
  • Aria-Live: Uses polite or assertive live regions via GetAnnouncementText callback.
  • Minimum Timeout: 5000ms minimum enforced for users who need time to read.
  • Pause on Interaction: Timers pause on hover and focus to give users control.
  • Keyboard Hotkey: Configurable hotkey (e.g., F8) to focus the toast region.
  • Localization: AriaLabel must be provided by the user for proper localization.
An unhandled error has occurred. Reload X