Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
5ef0f8f
Initial Toast work
vnbaaij Feb 24, 2026
692ab4e
Merge
vnbaaij Mar 10, 2026
deab381
Make it work with toast service
vnbaaij Mar 10, 2026
bf4f316
Merge branch 'dev-v5' into users/vnbaaij/dev-v5/toast-part1
vnbaaij Mar 16, 2026
75f495f
Big refactor. Use a FluentToast and FluentProgressToast as component …
vnbaaij Mar 18, 2026
0ab98a5
Merge branch 'dev-v5' into users/vnbaaij/dev-v5/toast-part1
vnbaaij Mar 18, 2026
7a85d82
Refactoring again
vnbaaij Mar 19, 2026
de285b1
Make dismiss use close action
vnbaaij Mar 20, 2026
623740e
Fix closing animation
vnbaaij Mar 20, 2026
0a247af
Fix layout, styling and animations
vnbaaij Mar 23, 2026
0b3f017
Implement action calbacks, add close reason, remove ToastResult, rena…
vnbaaij Mar 24, 2026
d6a5275
Implement queueing
vnbaaij Mar 24, 2026
82c6326
Add more tests, some small refactoring
vnbaaij Mar 24, 2026
cc4fee6
Merge branch 'dev-v5' into users/vnbaaij/dev-v5/toast-part1
vnbaaij Mar 25, 2026
c5b99d3
Add more tests, add xml comments, process Copilot review comments
vnbaaij Mar 25, 2026
09ed468
Merge branch 'users/vnbaaij/dev-v5/toast-part1' of https://github.com…
vnbaaij Mar 25, 2026
efda6fc
Rename and remove parameters, adjust tests
vnbaaij Mar 25, 2026
c2b270e
Process Copilot recommendation
vnbaaij Mar 25, 2026
77c6836
Merge branch 'dev-v5' into users/vnbaaij/dev-v5/toast-part1
vnbaaij Mar 27, 2026
9c65808
Finalize work, add docs and examples
vnbaaij Mar 27, 2026
904ad41
Update tests
vnbaaij Mar 27, 2026
934beb5
Added 1 new test and removed 1 obsolete test
vnbaaij Mar 27, 2026
1bb96d8
Process Copilot comments
vnbaaij Mar 27, 2026
57171c8
- Add `Inverted` parameter wit example, tests and docs
vnbaaij Mar 30, 2026
6da5e66
Add and fix test
vnbaaij Mar 30, 2026
f731ac2
Merge branch 'dev-v5' into users/vnbaaij/dev-v5/toast-part1
dvoituron Apr 3, 2026
affe63d
Delete AssemblyInfo.cs
vnbaaij Apr 3, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
@inject IToastService ToastService

<FluentButton OnClick="@OpenToastAsync">
Make toast
</FluentButton>

@code {
int clickCount = 0;

private async Task OpenToastAsync()
{
var result = await ToastService.ShowToastAsync(options =>
{
options.Intent = ToastIntent.Success;
options.Title = $"Toast title {++clickCount}";
options.Body = "This toast has a custom dismiss action.";
options.IsDismissable = true;
options.DismissAction = "Undo";
options.DismissActionCallback = () =>
{
Console.WriteLine("Undo action executed.");
return Task.CompletedTask;
};
options.OnStatusChange = (e) =>
{
Console.WriteLine($"Status changed: {e.Id} - {e.Status}");
};

});
Console.WriteLine($"Toast result: {result}");
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
@inject IToastService ToastService

<FluentButton OnClick="@OpenToastAsync">
Make toast
</FluentButton>

@code {
int clickCount = 0;

private async Task OpenToastAsync()
{
var result = await ToastService.ShowToastAsync(options =>
{
options.Title = $"Toast title {++clickCount}";
options.Body = "Toasts are used to show brief messages to the user.";
options.Subtitle = "subtitle";
options.QuickAction1 = "Action";
options.QuickAction1Callback = () =>
{
Console.WriteLine("Action 1 executed.");
return Task.CompletedTask;
};
options.QuickAction2 = "Action";
options.QuickAction2Callback = () =>
{
Console.WriteLine("Action 2 executed.");
return Task.CompletedTask;
};
options.IsDismissable = true;
options.OnStatusChange = (e) =>
{
Console.WriteLine($"Status changed: {e.Id} - {e.Status}");
};

});
Console.WriteLine($"Toast result: {result}");
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
@inject IToastService ToastService

<FluentButton @ref="openToastButton" OnClick="@OpenToastAsync">
Make toast
</FluentButton>

@code {
FluentButton openToastButton = default!;

private static RenderFragment BuildProgressContent(int value) =>
@<div>
<FluentProgressBar Min="0" Max="100" Value="value" Width="100%" />
@($"{value}% complete")
</div>;

private async Task OpenToastAsync()
{
openToastButton.SetDisabled(true);

var instance = await ToastService.ShowToastInstanceAsync(options =>
{
options.Type = ToastType.DeterminateProgress;
options.Icon = new Icons.Regular.Size20.ArrowDownload();
options.Title = "Downloading file";
options.BodyContent = BuildProgressContent(0);
});

for (int i = 0; i <= 100; i += 10)
{
await Task.Delay(500); // Simulate work being done
await instance.UpdateAsync(options =>
{
options.BodyContent = BuildProgressContent(i);
});
}

openToastButton.SetDisabled(false);
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
@inject IToastService ToastService

<FluentStack HorizontalGap="16">
<FluentButton @ref="openToastButton" OnClick="@OpenToastAsync">
Make toast
</FluentButton>
<FluentButton OnClick="@FinishProcessAsync">
Finish process
</FluentButton>
</FluentStack>

@code {
int clickCount = 0;
FluentButton openToastButton = default!;

private async Task OpenToastAsync()
{
// Disable the button to prevent multiple toasts from being opened.
// In a real app, you would likely want to track the toast ID and only disable if that specific toast is open.
openToastButton.SetDisabled(true);
var result = await ToastService.ShowToastAsync(options =>
{
options.Id = "indeterminate-toast";
options.Timeout = 0;
options.Type = ToastType.IndeterminateProgress;
options.Intent = ToastIntent.Success;
options.Title = $"Toast title {++clickCount}";
options.Body = "No idea when this will be finished...";
});
Console.WriteLine($"Toast result: {result}");
}

private async Task FinishProcessAsync()
{
// In a real app, you would likely keep track of the toast ID and update that specific toast.
await ToastService.DismissAsync("indeterminate-toast");
// Enable the button again so a new toast can be opened.
openToastButton.SetDisabled(false);
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
@inject IToastService ToastService

<FluentButton OnClick="@OpenToastAsync">
Make toast
</FluentButton>

@code {
int clickCount = 0;

private async Task OpenToastAsync()
{
var result = await ToastService.ShowToastAsync(options =>
{
options.Intent = ToastIntent.Info;
options.Title = $"Toast title {++clickCount}";
options.Body = "Toasts are used to show brief messages to the user.";
options.Subtitle = "subtitle";
options.QuickAction1 = "Action";
options.QuickAction1Callback = () =>
{
Console.WriteLine("Action 1 executed.");
return Task.CompletedTask;
};
options.IsDismissable = true;
options.DismissAction = "Close";
options.OnStatusChange = (e) =>
{
Console.WriteLine($"Status changed: {e.Id} - {e.Status}");
};
options.Inverted = true;
});
Console.WriteLine($"Toast result: {result}");
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
---
title: Toast
route: /Toast
category: 20|Components
icon: FoodToast
---

# Toast

A toast communicates the status of an action someone is trying to take or that something happened elsewhere in the app. Toasts are temporary surfaces.
Use them for information that's useful and relevant, but not critical.

The library provides a `FluentToast` component that can be used to display these notifications. To display a toast, you **must** use the `ToastService`. You use
the `ToastOptions` class to configure the toast's content and behavior.

## Types

Toasts generally fall into three categories: confirmation, progress, and communication. The toast component has slots that can be turned on and off to best
help people achieve their goals. The ideal configuration and usage of each toast type is described below:

### Confirmation toast

Confirmation toasts are shown to someone as a direct result of their action. A confirmation toast’s state can be success, error, warning,
informational, or progress.

### Progress toast

Progress toasts inform someone about the status of an operation they initiated.

### Communication toast

Communication toasts inform someone of messages from the system or another person’s actions. These messages can include mentions, event reminders, replies,
and system updates.
They include a call to action directly linking to a solution or the content that they reference. They can be either temporary or persistent. They’re
dismissible only if there is another surface, like a notification center, where the customer can find this content again later.

## Behavior

### Dismissal

Toasts can have timed, conditional, or express dismissals, dependent on their use case.

#### Timed dismissal

If there is no action to take, toast will time out after seven seconds. Timed dismissal is best when there is no further action to take, like for a successful
confirmation toast.

People who navigate via mouse can pause the timer by hovering over the toast. However, toasts that don’t include actions won’t receive keyboard focus for
people who navigate primarily by keyboard.

#### Conditional dismissal

Use conditional dismissal for toasts that should persist until a condition is met, like a progress toast that dismisses once a task is complete.

Don’t use toasts for necessary actions. If you need the encourage people to take an action before moving forward, try a more forceful surface like a message
bar or a dialog.

#### Express dismissal

Include the Close button to allow people to expressly dismiss toasts only if they can find that information again elsewhere, like in a notification center.

>[!Note] We do not have a way yet to facilitate showing toast messages on other surfaces like a notification center, so use the express dismissal option with
caution.

### Determinate and indeterminate progress

Progress toasts can be either determinate or indeterminate, depending on the needs of your app and the capabilities of the technology you’re building on.

When the completion time can be predicted, show a determinate progress bar and percentage of completion. Determinate progress bars offer a reliable user
experience since they communicate status and assure people things are still working.

If the completion time is unknown or its accuracy is unreliable, show an indeterminate spinner icon instead.

Although a specific type of toast needs to be specified through the `ToastOptions`, the library does not prevent you from showing both a spinner icon and a
progress bar in the same toast, but we recommend strongly against doing this.

## Accessibility

By using the `Intent` property (from `ToastOptions`) semantic styles, icons and aria-live regions and roles used in the toast are automatically applied.

All feedback states except info have an “assertive” aria-live and interrupt any other announcement a screen reader is making. Too many interruptions can disrupt someone’s flow,
so don’t overload people with too many assertive toasts.

## Examples

### Default

This example shows a toast with the default configuration, which includes a title and a message. It also has the default intent of `Info`, which applies the corresponding icon.
It shows 2 action links in the footer, which is the maximum number of what is possible for a toast.

{{ FluentToastDefault }}

### Custom dismissal

This example shows a toast with a custom dismissal configuration. It uses an action link (with a custom callback) instead of the standard dismiss icon to dismiss the toast.

{{ FluentToastCustomDismiss }}

### Inverted toast

You can use the `Inverted` property to show a toast with an inverted color scheme. This allows for showing a dark toast on a light background, or a light toast on a dark background.

>[!Note] When setting `IsDismissable` to `true`, without setting a custom `DismissAction`, a toast will render a default dismiss button using the `FluentButton` component.
As a `FluentButton` has no notion of an `Inverted` property, you need to set an explicit `DismissAction` so a inverted aware link is rendered instead of the default button.

{{ FluentToastInverted }}

### Indeterminate progress

This example shows a toast with an indeterminate progress configuration. Timeout has been set to zero, so the toast will never close by itself. Use the 'Finish process' button to dismiss the toast.

{{ FluentToastIndeterminateProgress }}

### Determinate progress

This example shows how a toast can be updated during a longer running process (with a predictable duration).

{{ FluentToastDeterminateProgress }}

## API ToastService

{{ API Type=ToastService }}

## API FluentToast

{{ API Type=FluentToast }}

## API ToastOptions

{{ API Type=ToastOptions Properties=All }}

## API FluentToastProvider

{{ API Type=FluentToastProvider }}
Loading
Loading