true-perfect-code
Version: 1.1.69

P11Toast Service

The P11Toast is a service component that allows you to display temporary, non-blocking notifications to users. It leverages Bootstrap's toast functionality for consistent styling and behavior. To display a toast, you inject the P11ToastService and call its methods with a ToastRequest object.
Note: The P11Toast service requires a TpcToastContainer component to be present in your application's layout (e.g., in MainLayout.razor or App.razor) to render the toasts. This container manages the display and dismissal of all active toast notifications.

Required Configuration for P11Toast

To use the P11Toast service, you must perform a few one-time setup steps in your Blazor application:

1. Register the Service in Program.cs

The IToastService must be registered in the dependency injection container.


// In Program.cs (Blazor Server or Blazor WebAssembly)
builder.Services.AddScoped<IToastService, ToastService>();
                
2. Add the Component to your Layout

The P11Toast component, which acts as the container, needs to be added to your application's main layout file (e.g., Routes.razor or App.razor).


// In Routes.razor
<Router AppAssembly="typeof(Layout.MainLayout).Assembly">
  <Found Context="routeData">
    <RouteView RouteData="routeData" DefaultLayout="typeof(Layout.MainLayout)" />
    <FocusOnNavigate RouteData="routeData" Selector="h1" />
  </Found>
</Router>

<P11Toast />
                
3. Add the Namespace to _Imports.razor

To easily access the component without a full namespace, add the following line:


// In _Imports.razor
@using p11.UI
@using p11.UI.Models
                
4. Inject the Service for Usage

Finally, inject the service into any component where you want to display a toast.


// In your .razor component or its code-behind
@inject IToastService ToastService
                


Examples

These examples show the different toast types and configurations available through the IToastService.

Standard Toast Types

Click to display different standard toasts.

Implementation

<h4 class="mb-3">Standard Toast Types</h4>
<p>Click to display different standard toasts.</p>
<div class="d-flex flex-wrap gap-2 align-items-center">
    <button class="btn btn-primary" @onclick="ShowInfoToast">Info Toast</button>
    <button class="btn btn-success" @onclick="ShowSuccessToast">Success Toast</button>
    <button class="btn btn-warning" @onclick="ShowWarningToast">Warning Toast</button>
    <button class="btn btn-danger" @onclick="ShowErrorToast">Error Toast</button>
</div>
@code {
    private ToastPosition selectedPosition = ToastPosition.BottomEnd;

    private async Task ShowInfoToast()
    {
        await ToastService.ShowInfoAsync("This is a standard info message.", "Information", position: selectedPosition);
    }

    private async Task ShowSuccessToast()
    {
        await ToastService.ShowSuccessAsync("The action was successfully completed.", "Success", position: selectedPosition);
    }

    private async Task ShowWarningToast()
    {
        await ToastService.ShowWarningAsync("Please check your input.", "Warning", position: selectedPosition);
    }

    private async Task ShowErrorToast()
    {
        await ToastService.ShowErrorAsync("An unexpected error occurred.", "Error", position: selectedPosition);
    }
}

@*
If the component does not work, then check:

1. whether the service is registered in Program.cs
(builder.Services.AddScoped<IToastService, ToastService>();)

2. whether the component is added in Routes.razor
<Router AppAssembly="typeof(Layout.MainLayout).Assembly">
 <Found Context="routeData">
 <RouteView RouteData="routeData" DefaultLayout="typeof(Layout.MainLayout)" />
 <FocusOnNavigate RouteData="routeData" Selector="h1" />
 </Found>
</Router>
<P11Toast />

3. whether namespace has been added in _Imports.razor
@using p11.UI
@using p11.UI.Models

4. whether you have defined DI in your Page/Codebehind
@inject IToastService ToastService / [Inject] private IToastService ToastService { get; set; }
*@


Toast Positioning

Select a position and click the button to show the toast there.

Implementation

<h4 class="mb-3">Toast Positioning</h4>
<p>Select a position and click the button to show the toast there.</p>
<div class="d-flex flex-wrap gap-2 align-items-center">
    <div class="dropdown">
        <select @bind="selectedPosition" class="form-select">
            <option value="">Select Toast Position...</option>
            @foreach (var position in Enum.GetValues(typeof(ToastPosition)))
            {
                <option value="@position">@position</option>
            }
        </select>
    </div>
    <button class="btn btn-secondary" @onclick="ShowToastWithPosition">Positioned Toast</button>
</div>
@code {
    private ToastPosition selectedPosition = ToastPosition.BottomEnd;

    private async Task ShowToastWithPosition()
    {
        await ToastService.ShowInfoAsync(
            "This is a positioned toast.",
            "Positioned",
            position: selectedPosition);
    }
}

@*
If the component does not work, then check:

1. whether the service is registered in Program.cs
(builder.Services.AddScoped<IToastService, ToastService>();)

2. whether the component is added in Routes.razor
<Router AppAssembly="typeof(Layout.MainLayout).Assembly">
 <Found Context="routeData">
 <RouteView RouteData="routeData" DefaultLayout="typeof(Layout.MainLayout)" />
 <FocusOnNavigate RouteData="routeData" Selector="h1" />
 </Found>
</Router>
<P11Toast />

3. whether namespace has been added in _Imports.razor
@using p11.UI
@using p11.UI.Models

4. whether you have defined DI in your Page/Codebehind
@inject IToastService ToastService / [Inject] private IToastService ToastService { get; set; }
*@


Custom Content & ARIA Mode

These examples demonstrate using ShowCustomAsync for advanced scenarios, including setting the ariaLiveMode.

Implementation

<h4 class="mb-3">Custom Content & ARIA Mode</h4>
<p>These examples demonstrate using <code>ShowCustomAsync</code> for advanced scenarios, including setting the <code>ariaLiveMode</code>.</p>
<div class="d-flex flex-wrap gap-2 align-items-center">
    <button class="btn btn-info text-white" @onclick="ShowCustomToast">Custom Toast</button>
    <button class="btn btn-danger" @onclick="ShowAssertiveErrorToast">Assertive Error Toast</button>
</div>
@code {
    private ToastPosition selectedPosition = ToastPosition.BottomEnd;

    private async Task ShowCustomToast()
    {
        var customContent = (RenderFragment)(builder =>
        {
            builder.OpenElement(0, "div");
            builder.AddMarkupContent(1, "<b>This is a toast with</b> <u>custom</u> HTML content.");
            builder.CloseElement();
        });

        await ToastService.ShowCustomAsync(
            content: customContent,
            title: "Custom",
            durationMs: 6000,
            ariaLiveMode: "polite",
            position: selectedPosition);
    }

    private async Task ShowAssertiveErrorToast()
    {
        var customContent = (RenderFragment)(builder =>
        {
            builder.OpenElement(0, "div");
            builder.AddMarkupContent(1, "Important error: immediate screen reader announcement!");
            builder.CloseElement();
        });

        await ToastService.ShowCustomAsync(
            content: customContent,
            title: "Immediate Error",
            durationMs: 6000,
            ariaLiveMode: "assertive",
            position: selectedPosition);
    }
}

@*
If the component does not work, then check:

1. whether the service is registered in Program.cs
(builder.Services.AddScoped<IToastService, ToastService>();)

2. whether the component is added in Routes.razor
<Router AppAssembly="typeof(Layout.MainLayout).Assembly">
 <Found Context="routeData">
 <RouteView RouteData="routeData" DefaultLayout="typeof(Layout.MainLayout)" />
 <FocusOnNavigate RouteData="routeData" Selector="h1" />
 </Found>
</Router>
<P11Toast />

3. whether namespace has been added in _Imports.razor
@using p11.UI
@using p11.UI.Models

4. whether you have defined DI in your Page/Codebehind
@inject IToastService ToastService / [Inject] private IToastService ToastService { get; set; }
*@


API Reference

The core functionality of the toast system is provided via the IToastService interface. The table below describes the available methods for displaying toasts.

Method Description
ShowInfoAsync(string message, string title = "Information", int durationMs = 5000, bool isDismissible = true, ToastPosition position = ToastPosition.BottomEnd) Displays an informational toast.
ShowSuccessAsync(string message, string title = "Success", int durationMs = 5000, bool isDismissible = true, ToastPosition position = ToastPosition.BottomEnd) Displays a success toast.
ShowWarningAsync(string message, string title = "Warning", int durationMs = 5000, bool isDismissible = true, ToastPosition position = ToastPosition.BottomEnd) Displays a warning toast.
ShowErrorAsync(string message, string title = "Error", int durationMs = 0, bool isDismissible = true, ToastPosition position = ToastPosition.BottomEnd) Displays an error toast. Note: This method does not support ariaLiveMode.
ShowCustomAsync(RenderFragment content, string title = "Custom Notification", int durationMs = 5000, bool isDismissible = true, string ariaLiveMode = "polite", ToastPosition position = ToastPosition.BottomEnd) Displays a custom toast with user-defined Blazor content and allows overriding the ARIA live region mode. This is the recommended method for toasts with assertive accessibility needs.

ToastRequest Properties

The ToastRequest class is used to define a detailed configuration for a toast, especially when using ShowToastRequested or ShowCustomAsync.

Property Type Default Description
Id Guid Guid.NewGuid() Gets or sets the unique identifier for this toast instance. Used internally by the TpcToastContainer to manage individual toasts.
Title string null Gets or sets the title displayed in the header of the toast. Optional.
Message string null Gets or sets the main message text to display in the body of the toast. This property is used for standard text-based toasts.
Type ToastType ToastType.Info Gets or sets the type or purpose of the toast, influencing its icon and default styling.
IconClass string null Gets or sets an optional CSS class for a custom icon. If specified, this class overrides the default icon determined by the Type.
DurationMs int 0 Gets or sets the duration (in milliseconds) the toast should be displayed. A value of 0 indicates the toast should remain until manually dismissed.
IsDismissible bool true Gets or sets a value indicating whether the toast can be manually closed by the user. If true, a close button will typically be displayed.
CustomContent RenderFragment null Gets or sets custom Blazor content for the toast body. If this is provided, the Message property will typically be ignored.
AriaLiveMode string "polite" Gets or sets the ARIA live region mode for this specific toast. "polite": Screen reader announces the update when it's idle. Suitable for non-critical messages. "assertive": Screen reader immediately announces the update, interrupting current speech. Suitable for critical messages (e.g., errors). Defaults to "polite" but can be overridden, especially for ToastType.Error.
Timestamp DateTime DateTime.UtcNow Timestamp when the toast request was created.
DismissCallback Action<Guid> - An internal callback action used by the TpcToastContainer component to signal that this specific toast instance has been dismissed (either manually or automatically). This property is intended for internal use within the toast system.
An unhandled error has occurred. Reload 🗙