jackbsteinberg / std-toast

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Attribute or Style positioning?

jackbsteinberg opened this issue · comments

The research on popular toast libraries showed that many implementations gave an easy way to position the toast. That positioning, usually in the corners or the middle of the top / bottom, often bypassed CSS, and was passed in as an HTML attribute or field on a JavaScript object.

Should this pattern be emulated for ease of use of the toast, or should it be left up to the developer to manually position with CSS styling.

Additional Considerations for position:

  • The positions suggested are as follows:
    • "top-left"
    • "top-center"
    • "top-right"
    • "middle-left"
    • "middle-center"
    • "middle-right"
    • "bottom-left"
    • "bottom-center"
    • "bottom-right"
  • These are physical positions; should we use logical ones instead?
  • Should there be a system default for positions (e.g. should Android toasts show up in a different location from macOS toasts)?
  • How will we allow the developer to easily tweak the positioning?

I would expect middle-left and middle-right to be very rare, it might be a good idea to omit those in favour of just middle.

Sometimes with toasts that contain a lot of content (“this website uses cookies” kinds of warnings, for example), it is preferable to stretch them horizontally, instead of displaying in the corner or the center. I suggest to consider adding top-stretch and bottom-stretch standard positions for those use cases.

Having logical values instead of physical would be great indeed.

@jackbsteinberg I think you did a brief survey of the libraries in https://github.com/jackbsteinberg/std-toast/tree/master/study-group and what their default position was; would you mind posting that here? (Or maybe editing the study group document).

Similarly I agree that stretching is also a commonly seen default, especially on mobile.

I did a brief survey of the default positioning for libraries and got these results:

  • Top-right (3): react-toastify, ngx-toastr, Sweet Alert 2
  • Bottom-stretch (3): Ionic, Android Snackbar, Android Toast
  • Bottom-left (2): Material Design, Polymer
  • Top-stretch (1): Blueprint
  • Bottom-right (1): Notyf

It seems to me as far as desktop toasts are concerned that top-right is the usual default, with two of the most popular libraries surveyed taking that approach. Three libraries used bottom-stretch as well, all three of built for mobile, which begs the interesting question of should we have a separate default for web / mobile? One thing that's certainly confirmed is the need for top-stretch and bottom-stretch values, specifically to support the mobile web, updating the spec to reflect that soon.

Is stretch orthogonal to position? It may not be common but e.g. right-stretch may be the right thing in vertical writing mode.

Vertical writing mode is an interesting concept to consider, which we could combat using logical properties, which is interesting and worth looking into.

As far as stretch is concerned we could add in right-stretch and left-stretch to cover all the bases, but there might be a solution that happens more automatically for the developer, so they don't have to specify in these edge cases. Support for logical properties could solve this issue.

As discussed offline, I'd expect some basic defaults for positioning... maybe top / bottom, but otherwise would expect positioning to be done via author CSS. Specifically to mitigate authors needing to set a positioning attribute for each instance of the component declared in the DOM, as well as a means to reposition via media queries for small screen / zoomed in desktop viewports.

So I'm generally of the opinion that we shouldn't do anything here, and let authors control things in CSS. This is contrary to most existing toast libraries (8/12 in the study group) but seems to fit better with the web platform's general approach.

(Note: in what follows I will use physical positions, like top/left, since they are most familiar to me. But everything translates to logical positions, like block-start/inline-start, as well.)

First, consider that providing a simple set of presets like "top right", "bottom middle", etc. won't be flexible enough. People will need to say exactly how far from the right, or the bottom, etc. In existing libraries they do this via stuff like

toast.setGravity(Gravity.TOP or Gravity.LEFT, 10, 10)

or

toast.warn("Warning Notification !", {
  position: toast.POSITION.BOTTOM_LEFT
});

plus

.Toastify__toast-container--top-right {
  top: 1.5em; /* instead of 1em */
}

So it seems like even if we went with the setGravity style, we'd end up with something like

showToast('...', { position: 'top-left', offsetTop: '10px', offsetLeft: '10px' });

or

std-toast { --position: top-left, --offset-top: 10px, --offset-left: 10px }

But... this isn't really much better than what we can get with just existing CSS positioning.


What do we get with existing CSS positioning? Well, it's a bit complicated because of default styles. Currently we've put the toast as a default 1em from bottom right. (Actually, block/inline-direction end.) That particular default isn't finalized, but we're almost certainly going to pick something; we wouldn't want the toast to be the first HTML element which is unusable without the page author adding their own styles. This means that common positioning scenarios look like the following:

.top-left-toast       { top: 10px; right: auto; bottom: auto; left: 10px; }
.bottom-left-toast    { top: auto; right: auto; bottom: 10px; left: 10px; }
.bottom-stretch-toast { top: auto; right: 10px; bottom: 10px; left: 10px; }

/* as usual centering things in CSS is hard. Let's rely on unimplemented awesomeness instead! */
.top-center-toast     { top: 10px; right: auto; bottom: auto; left: auto; justify-self: center; }

This doesn't seem so bad to me. I believe it gets even better if this other future CSS feature gets implemented:

.top-left-toast       { inset: 10px auto auto 10px; }
.bottom-left-toast    { inset: auto auto 10px 10px; }
.bottom-stretch-toast { inset: auto 10px 10px 10px; }

.top-center-toast     { inset: 10px auto auto auto; justify-self: center; }

Similarly if you wanted to set these things from JavaScript it could be as simple as

const toast = showToast('...');
toast.style.inset = '10px auto auto 10px';