"Toast" notifications #11807

Open
opened 2026-01-31 02:58:03 +00:00 by claunia · 3 comments
Owner

Originally created by @zadjii-msft on GitHub (Dec 15, 2020).

An idea I've been toying around with for a while, but haven't formalized.

"Toasts" are an Android UI paradigm - a transient notification that can be displayed to the user. These toasts can't be interacted with, and dismiss themselves after a brief timeout.
image

WinUI doesn't have Toasts, but it does have the TeachingTip. in the future, WinUI is planning on building this auto-dismiss behavior into the TeachingTip itself, but we're impatient.
image

Use cases that would be good for this:

  • A. #8514 - When we open a tab in another elevated window, it might be nice to display a toast to the user "A new tab was created in an elevated window"
  • B. As mentioned in #8135: we'll need a little UI element for displaying the Window IDs/names. Maybe a window-level toast would work?
  • C. Similar to the above, inspired by #5803, #5464, #8183: display a toast in each pane showing the Pane IDs
  • D. inspired by discussion in #8330: in that PR, we'll fall back to the profile's startingDirectory if the provided directory doesn't exist. In that case, we could display a toast to the user as well.
  • E. Feature Request: Show terminal size when resizing the window #2833
    • Maybe? This might not be the best example for a toast.
  • F. https://github.com/microsoft/terminal/pull/14425#issuecomment-1329164354 - display the notification as a Toast, instead of an OS-level notification
  • #17561: We thought about it, but also these Toasts are FAR too heavy for as lightweight a thing as we need for that.

From the above, there are two kinds of scenarios where we want Toasts: control-level and window-level.

  • A, B, D are all window-level. There's one Toast visible, at the window level. Changing tabs wouldn't hide this toast (this is important for D, where the toast would be fired as the new tab is opening, and we probably want the toast to persist in both the original tab and the tab that's created).
  • C is a control-level toast. Each pane would display a toast. Changing tabs would hide these toasts.

I'm not prescribing any interactable UI in these toasts, but TeachingTips do allow buttons and other rich content.

I'm sure there are other things we could do too. This issue is so I don't lose track of the possible scenarios.

Other things:

  • Something like "Unable to rename window. Another window with that name already exists."
Originally created by @zadjii-msft on GitHub (Dec 15, 2020). An idea I've been toying around with for a while, but haven't formalized. ["Toasts"](https://developer.android.com/guide/topics/ui/notifiers/toasts) are an Android UI paradigm - a transient notification that can be displayed to the user. These toasts can't be interacted with, and dismiss themselves after a brief timeout. ![image](https://user-images.githubusercontent.com/18356694/102251267-32b57200-3eca-11eb-9c1b-dc64e98a28a3.png) WinUI doesn't have Toasts, but it does have the `TeachingTip`. in the future, WinUI is planning on building this auto-dismiss behavior into the `TeachingTip` itself, but we're impatient. ![image](https://user-images.githubusercontent.com/18356694/102251368-51b40400-3eca-11eb-9762-75012bc038db.png) Use cases that would be good for this: * [ ] **A.** #8514 - When we open a tab in another elevated window, it might be nice to display a toast to the user "A new tab was created in an elevated window" * [x] **B.** As mentioned in #8135: we'll need a little UI element for displaying the Window IDs/names. Maybe a window-level toast would work? * [ ] **C.** Similar to the above, inspired by #5803, #5464, #8183: display a toast in each pane showing the Pane IDs - #10708 * [ ] **D.** inspired by discussion in #8330: in that PR, we'll fall back to the profile's `startingDirectory` if the provided directory doesn't exist. In that case, we could display a toast to the user as well. * [ ] **E.** Feature Request: Show terminal size when resizing the window #2833 - Maybe? This might not be the best example for a toast. * [ ] **F.** https://github.com/microsoft/terminal/pull/14425#issuecomment-1329164354 - display the notification as a Toast, instead of an OS-level notification * [ ] #17561: We thought about it, but also these Toasts are FAR too heavy for as lightweight a thing as we need for that. From the above, there are two kinds of scenarios where we want Toasts: control-level and window-level. * A, B, D are all window-level. There's one Toast visible, at the window level. Changing tabs wouldn't hide this toast (this is important for D, where the toast would be fired as the new tab is opening, and we probably want the toast to persist in both the original tab and the tab that's created). * C is a control-level toast. Each pane would display a toast. Changing tabs would hide these toasts. I'm not prescribing any interactable UI in these toasts, but `TeachingTips` do allow buttons and other rich content. I'm sure there are other things we could do too. This issue is so I don't lose track of the possible scenarios. Other things: * [x] Something like "Unable to rename window. Another window with that name already exists."
claunia added the Issue-FeatureProduct-TerminalArea-UserInterface labels 2026-01-31 02:58:03 +00:00
Author
Owner

@DHowett commented on GitHub (Dec 16, 2020):

Control level toasts also include the resize size indicator!

@DHowett commented on GitHub (Dec 16, 2020): Control level toasts also include the resize size indicator!
Author
Owner

@DHowett commented on GitHub (Dec 17, 2020):

Backlog approved.

@DHowett commented on GitHub (Dec 17, 2020): Backlog approved.
Author
Owner

@zadjii-msft commented on GitHub (Jan 20, 2021):

Alright, so I tried to do this today. Here's what I learned:

  • It works fairly well for the app-level toasts, where the notification is centered in the bottom of the window.
  • The TeachingTip is definitely focusable, or in the tab order, or something. So it's certainly possible for it to steal the focus from the TermControl.
    • This is particularly noticeable with multiple toasts (like a per-control toast).
    • I found the focus commonly getting tossed back to the TabViewItem, not the TermControl. That's aggressively annoying.
  • If you create a TeachingTip, and don't give it a Target, it's always going to be placed relative to the XAML ROOT, not _whatever thing is the parent element of the TeachingTip. This is particularly painful because none of the placement options allow you to place it within the bounds of the target. They all want to be outside the target, on the side somewhere.
    • The closest I could get was to add a PlacementMargin of -80, -80, -80, -80, which seemed to work alright in a XAML studio scratch page, but doesn't work well in the Terminal itself.
      image
      • -80, -80, -80, -80 is obviously contrived. I should only need to set one of those to -80, right? But it's not clear if it's Top or Bottom that needs to be set.
  • If the TeachingTip isn't entirely visible, it just destroys itself. Maybe this is related to ShouldConstrainToRootBounds?
    • This is particularly problematic for smaller panes.
  • Maybe I'm daft, but I can't seem to make the TeachingTips smaller? Like, "Pane 1" is not a whole lot of text.
    • This exacerbates the previous point about the TeachingTips just dying immediately.
  • There's an upstream bug tracking the fact that TeachingTips will reserve space for the Title and Subtitle, even if one is null/empty. We probably only want one at a time.
  • Someone needs to hold a reference to the TeachingTip/Toast, so we can dismiss it properly at the end of the timer. The way I did that was with two classes:
    • Toast was the container for the Timer and the TeachingTip, and after the timeout, would hide the TeachingTip. It shouldn't be constructed on it's own though.
    • Toaster was the container for "Thing to create and own Toasts". It would be able to MakeToast on a given (optional) UI element, and would hold all the Toasts it creates, then remove them when their timer expires.
    • This felt like madness, but it worked? So the TerminalPage had a Toaster it could use to send toasts. It did not feel like a natural extension of TeachingTip.

My work is over in dev/migrie/f/com.fabrikam.toaster. Feel free to check it out if interested.

@zadjii-msft commented on GitHub (Jan 20, 2021): Alright, so I tried to do this today. Here's what I learned: * It works fairly well for the app-level toasts, where the notification is centered in the bottom of the window. * The `TeachingTip` is definitely focusable, or in the tab order, or something. So it's certainly possible for it to steal the focus from the `TermControl`. - This is particularly noticeable with multiple toasts (like a per-control toast). - I found the focus commonly getting tossed back to the `TabViewItem`, not the `TermControl`. That's aggressively annoying. * If you create a `TeachingTip`, and don't give it a `Target`, it's always going to be placed relative to the _XAML ROOT_, not _whatever thing is the parent element of the `TeachingTip`. This is particularly painful because none of the placement options allow you to place it within the bounds of the target. They all want to be outside the target, on the side somewhere. - The closest I could get was to add a `PlacementMargin` of `-80, -80, -80, -80`, which seemed to work alright in a XAML studio scratch page, but doesn't work well in the Terminal itself. ![image](https://user-images.githubusercontent.com/18356694/105247063-cae1ef00-5b39-11eb-8bee-cf499753268c.png) - `-80, -80, -80, -80` is obviously contrived. I _should_ only need to set one of those to -80, right? But it's not clear if it's `Top` or `Bottom` that needs to be set. * If the TeachingTip isn't entirely visible, it just destroys itself. Maybe this is related to [`ShouldConstrainToRootBounds`](https://docs.microsoft.com/en-us/windows/winui/api/microsoft.ui.xaml.controls.teachingtip.shouldconstraintorootbounds?view=winui-2.5#Microsoft_UI_Xaml_Controls_TeachingTip_ShouldConstrainToRootBounds)? - This is particularly problematic for smaller panes. * Maybe I'm daft, but I can't seem to make the `TeachingTips` _smaller_? Like, "Pane 1" is not a whole lot of text. - This exacerbates the previous point about the `TeachingTips` just dying immediately. * There's an upstream bug tracking the fact that `TeachingTips` will reserve space for the `Title` _and_ `Subtitle`, even if one is null/empty. We probably only want one at a time. * Someone needs to hold a reference to the `TeachingTip`/`Toast`, so we can dismiss it properly at the end of the timer. The way I did that was with two classes: - `Toast` was the container for the Timer and the TeachingTip, and after the timeout, would hide the TeachingTip. It shouldn't be constructed on it's own though. - `Toaster` was the container for "Thing to create and own `Toast`s". It would be able to `MakeToast` on a given (optional) UI element, and would hold all the `Toast`s it creates, then remove them when their timer expires. - This felt like madness, but it worked? So the `TerminalPage` had a `Toaster` it could use to send toasts. It did _not_ feel like a natural extension of `TeachingTip`. My work is over in `dev/migrie/f/com.fabrikam.toaster`. Feel free to check it out if interested.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/terminal#11807