jackbsteinberg/std-toast

Should toasts be in the top layer, or just use last-child-of-body?

Opened this issue · 4 comments

How do we ensure toasts show up "on top" of an app?

One strategy is minimal: the toast has a UA default style of z-index: 1, and then developers are given guidance to generally place it as the last element of their <body>---plus the showToast() API which guides them down this path by default. This will mean that most of the time, it will be above most things, but developers can explicitly be on top of the toast using higher z-index values or placing things after it in the DOM order. (Note: #16 asks us to document this pattern, under the assumption that we choose it. And we probably should pick this to start with, at least.)

Additionally, this allows developers to keep the toast constrained to a stacking context, by placing it in a different element instead of at the end of <body>. (This is a feature that several existing libraries support, per https://github.com/jackbsteinberg/std-toast/tree/master/study-group "display in container".)

Another strategy is to put the toast in the top layer, which is currently used for only <dialog> (Chrome-only) and fullscreen. It's kind of under-explored territory. The next step if we wanted to go this route would be to flesh out the top layer concept further, per whatwg/html#4633. In particular, as noted there, I'd be interested in how native platforms handle the top layer concept, and whether/how their toasts use it.

One thing that occurs to me is that if we don't use the top layer strategy, then toasts will probably not show up while in fullscreen, unless you fullscreen the whole <body>, or specifically append the toast to the fullscreened element instead of to <body>. I'm unsure whether that's good or bad, but I lean toward bad.

I don't think using the top layer is a good idea. I'm pretty sure that the top layer has problematic
issues in its spec and implementation (*). The reason I say that is that the idea of forcing content in the DOM to the front will cause problems having to do with the way that that content interacts with its ancestors - transforms, stacking, containing block, scrolling, filters, etc.

The current plan (use z-index: 1 and otherwise no new concept) is good in that it doesn't add new concepts, but potentially bad in that the toast is not guaranteed to not be occluded. Occlusion can come from stacking order, but it can also come from clipping. e.g. what if the element that has a toast is inside an element that is clipped? Should the toast show anyway? Tooltips and other similar UX rendered within DOM have the same problem.

I'm not sure what the best answer is. I do have a strong view that we shouldn't add any new concepts to the rendering system. :)

This is riffing, but one thing could be to have the toast be a special descendant of another element that guarantees good stacking order. e.g.

std:content-with-toast
std:the-content...</>
std::toastToast!</>
</>

And we would force "the-content" to be a stacking context with z-index less than the toast. Developers would be required to put the content that has a toast under a content-with-toast element.

(*) Though to be honest I have not done a thorough appraisal (yet).

I'm not sure what the best answer is. I do have a strong view that we shouldn't add any new concepts to the rendering system. :)

I think there's a pretty strong demand from web developers for some solution in this area, which might require new concepts. I'm unsure whether toast falls into "this area" though, or whether it's just for dialogs/tooltips/context menus/...

If we did want to go this route, I was thinking fixing (and exposing an API for) top layer would be the way to go.

This is riffing, but one thing could be to have the toast be a special descendant of another element that guarantees good stacking order. e.g.

Maybe the thing to do here would be to encourage people to use

<body>
<main>...</main>
<std-toast></std-toast>
</body>

i.e. put all their stuff in main, and make sure main does not have z-index > 1. This aligns with existing best practices anyway, roughly speaking. (Main may have other siblings which you would want to similarly constrain...)

jouni commented

I think there's a pretty strong demand from web developers for some solution in this area

Strong support for this claim from me on behalf of Vaadin at least.

which might require new concepts. I'm unsure whether toast falls into "this area" though, or whether it's just for dialogs/tooltips/context menus/...

Here’s a proposal regarding that (from @platosha): https://discourse.wicg.io/t/proposal-position-viewport-scheme/3361

I’m not sure why toasts would be different from tooltips or other overlay elements. Can you elaborate your thoughts there?

jouni commented

i.e. put all their stuff in main, and make sure main does not have z-index > 1.

That seems like the easiest solution. But in practice, it can be cumbersome to do, at least with current libraries like Polymer or LitElement, which want you to place all HTML in a single template that ends up inside the element’s shadow root.

Requiring to put toasts in main also open up the contents of the toasts to global CSS conflicts and also force the developer to write any CSS targeting that content in a way that guards against conflicts.