-
Notifications
You must be signed in to change notification settings - Fork 467
[dev-v5] Add Toast #4584
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
[dev-v5] Add Toast #4584
Changes from 22 commits
Commits
Show all changes
32 commits
Select commit
Hold shift + click to select a range
5ef0f8f
Initial Toast work
vnbaaij 692ab4e
Merge
vnbaaij deab381
Make it work with toast service
vnbaaij bf4f316
Merge branch 'dev-v5' into users/vnbaaij/dev-v5/toast-part1
vnbaaij 75f495f
Big refactor. Use a FluentToast and FluentProgressToast as component …
vnbaaij 0ab98a5
Merge branch 'dev-v5' into users/vnbaaij/dev-v5/toast-part1
vnbaaij 7a85d82
Refactoring again
vnbaaij de285b1
Make dismiss use close action
vnbaaij 623740e
Fix closing animation
vnbaaij 0a247af
Fix layout, styling and animations
vnbaaij 0b3f017
Implement action calbacks, add close reason, remove ToastResult, rena…
vnbaaij d6a5275
Implement queueing
vnbaaij 82c6326
Add more tests, some small refactoring
vnbaaij cc4fee6
Merge branch 'dev-v5' into users/vnbaaij/dev-v5/toast-part1
vnbaaij c5b99d3
Add more tests, add xml comments, process Copilot review comments
vnbaaij 09ed468
Merge branch 'users/vnbaaij/dev-v5/toast-part1' of https://github.com…
vnbaaij efda6fc
Rename and remove parameters, adjust tests
vnbaaij c2b270e
Process Copilot recommendation
vnbaaij 77c6836
Merge branch 'dev-v5' into users/vnbaaij/dev-v5/toast-part1
vnbaaij 9c65808
Finalize work, add docs and examples
vnbaaij 904ad41
Update tests
vnbaaij 934beb5
Added 1 new test and removed 1 obsolete test
vnbaaij 1bb96d8
Process Copilot comments
vnbaaij 57171c8
- Add `Inverted` parameter wit example, tests and docs
vnbaaij 6da5e66
Add and fix test
vnbaaij f731ac2
Merge branch 'dev-v5' into users/vnbaaij/dev-v5/toast-part1
dvoituron affe63d
Delete AssemblyInfo.cs
vnbaaij 603533a
Use LibraryConfig for ToastProvider settings
vnbaaij 7549795
Remove a couple of toast now that provider doesn't have parameters an…
vnbaaij 0a23f74
Merge branch 'dev-v5' into users/vnbaaij/dev-v5/toast-part1
vnbaaij 212f8ad
Merge branch 'dev-v5' into users/vnbaaij/dev-v5/toast-part1
vnbaaij 252302d
Merge branch 'dev-v5' into users/vnbaaij/dev-v5/toast-part1
vnbaaij File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
32 changes: 0 additions & 32 deletions
32
...ples/Demo/FluentUI.Demo.Client/Documentation/Components/Toast/DebugPages/DebugToast.razor
This file was deleted.
Oops, something went wrong.
34 changes: 0 additions & 34 deletions
34
...mo/FluentUI.Demo.Client/Documentation/Components/Toast/DebugPages/DebugToastContent.razor
This file was deleted.
Oops, something went wrong.
33 changes: 33 additions & 0 deletions
33
...uentUI.Demo.Client/Documentation/Components/Toast/Examples/FluentToastCustomDismiss.razor
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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 dismss 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}"); | ||
| } | ||
| } | ||
|
|
||
39 changes: 39 additions & 0 deletions
39
...emo/FluentUI.Demo.Client/Documentation/Components/Toast/Examples/FluentToastDefault.razor
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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}"); | ||
| } | ||
| } | ||
|
|
40 changes: 40 additions & 0 deletions
40
....Demo.Client/Documentation/Components/Toast/Examples/FluentToastDeterminateProgress.razor
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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); | ||
| } | ||
| } | ||
|
|
41 changes: 41 additions & 0 deletions
41
...emo.Client/Documentation/Components/Toast/Examples/FluentToastIndeterminateProgress.razor
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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); | ||
| } | ||
| } | ||
|
|
125 changes: 125 additions & 0 deletions
125
examples/Demo/FluentUI.Demo.Client/Documentation/Components/Toast/FluentToast.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,125 @@ | ||
| --- | ||
| 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 acton link (with a custom callback) instead of the standard dismiss icon to dismiss the toast. | ||
vnbaaij marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| {{ FluentToastCustomDismiss }} | ||
|
|
||
| ### 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 }} | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.