Should infinite durations toasts default to having a close button?
Certainly a toast without an action and a timeout seems like it needs a close button.
This is an interesting issue. Let me sum up the status quo as of #18:
- If you use
showToast(), thecloseButtonoption defaults to true ifdurationends up asInfinity. (Either because you settype: "warning"/type: "error", or because you explicitly setduration: Infinity.) You can still create an infinite-duration no-closebutton toast manually withshowToast({ duration: Infinity, closeButton: false }). - If you use
<std-toast>.show(), the default duration is based on thetype=""attribute value, but the close button is controlled by theclosebutton=""attribute value. (It is not impacted by the duration, either the default inferred fromtype=""or explicitly passed toshow().) This means it is relatively easy to create an infinite-duration no-close-button toast, just by forgetting to set theclosebutton=""attribute. In particular the following are situations that might not work as desired:-
<std-toast type="error">.show(): default duration for warnings is infinite; no close button shown -
<std-toast>.show({ duration: Infinity }): explicitly set infinite in JS, but never setclosebutton=""in your HTML.
-
I see a few options here:
-
Make
show()automatically set theclosebutton=""attribute if the duration isInfinity, similar toshowToast.- This is somewhat strange, in that we usually leave content attributes to authors, and don't change them as a "side effect" of something else.
- But maybe it is OK; after all, the whole point of
.show()is to change theopen=""attribute, so maybe changing theclosebutton=""attribute as well is not a big step from there.
-
No longer control the close button via an attribute. Instead, it is only present via a
.show()/showToast()option.- I am a bit reluctant about this because "has a close button" doesn't seem very tied to showing, and saying that the only way you can control that is via show(), makes it a bit magic.
- In particular, previously show() could be fully emulated by user code, but now it is toggling internal state in a way that cannot be replicated easily, which could be annoying if people want to do custom show code (with, I dunno, animations or something).
-
CSS-centric:
- Remove the
closebutton=""attribute. To show the close button, you would usestd-toast::part(closebutton) { display: block; }. (It defaults todisplay: none.) - Add a
:state(infinite-duration)pseudo-class. This indicates matches when the element is being displayed for an infinite duration. Then the default stylesheet containsstd-toast:state(infinite-duration)::part(closebutton) { display: block }. - Now all changes to the default are done via CSS, such as
std-toast::part(closebutton) { display: ...; }.
- Remove the
(1) and (2) are both fairly easy. I think I am a bit more comfortable with (1) than (2).
(3) is interesting because it really leans on the idea of controlling the closebutton being a stylistic aspect of the element. Kind of like using CSS to control the "x" on <input type="search"> or the dropdown arrow on <select> or the marker for <details>. For example, design systems which say that all toasts must have a close button, would just have their own CSS rule for all toasts they produce, instead of requiring the HTML or JS to be changed for each toast.
I like (1) most as a strategy, but I agree that it seems strange to change the closeButton on a toast as a side effect of changing the duration. In addition, show() to me changes aspects of the toast with relation to their individual showings, whereas closeButton is more of a component of the toast itself.
As an alternative to avoid this weirdness, we could do nothing - make a recommendation that infinite-duration toasts should have a closeButton and leave it to developers to make that decision. There is something to be said about adding it automatically with type='warning|error' if those default to Infinity duration, but if a developer is manually adding duration: Infinity to their toasts I don't know that the toast should fill in a closeButton.