Open Link2Twenty opened 1 year ago
I already had this in <dialog></dialog>
. I solved it with multiple containers, but it would be great if the library handled this for us.
Just a gentle prompt that popover
will be in all browsers when Firefox 126 is released which is scheduled for 2024-05-14.
Currently, I am encountering this problem in a production project.
I am looking for solutions and temporary workarounds until the library handles it on its own.
Unfortunately there's no nice way to keep things in the topmost position. I imagine the whole toast container can be promoted to the top layer but everytime something new is promoted the toast container will need to be removed and re-promoted.
I have tried to play around with this a bit and have something that, although not optimal, makes it appear above other popover or dialog. However, I still have a serious problem to solve that I will explain at the end.
I will try to provide to you a example code ASAP, but by now i can explain it.
I created a React wrapper component of the <ToastContainer>
that is a <div>
with the popover
property set to manual
.
In the wrapper, I use the toast.OnChange
event to keep track of the identifiers of the toasts that are added and removed (side note: I don't know if exists but I would love to have a property similar to status
that tells me how many toasts currently exist, so I don't have to track it externally with status added
- removed
).
If the array of ids has content (there are toasts to show), I trigger showPopover
and otherwise, i trigger the hidePopover
.
Up to this point, it works wonderfully to appear above other <dialog>
or elements with popover
that already exist in the top-layer. But, what happens if while the toasts are being displayed, another <dialog>
or elements with popover
open?
The new element overlays the toast wrapper and hides it (partially or completely)! Just as @Link2Twenty mentioned in the previous comment.
"Solution": As @Link2Twenty indicated, reattaching the wrapper containing the <ToastContainer>
every time a <dialog>
or element with popover
opens, is not optimal, but I don't see another option!
For this, I have a function that does the hidePopover
of the wrapper and immediately after, in the next frame, I execute showPopover
again. Visually, the trick is almost unnoticeable.
But this function has to be executed every time a <dialog>
or elements with popover
open...
For popover, it's a simple (although not optimal) listener to the beforetoggle
or toggle
event for the entire document (although it has to be done in the capturing phase since it doesn't have a bubbling phase).
For the <dialog>
, oh, surprise! There is a close
event but no open
event!
So, with all the disgust in the world, the only thing I found was to overwrite the showModal
method of the HTMLDialogElement prototype (ugh).
Well, after this suffering, everything looks fine. Every time I open another <dialog>
or element with popover
while I have toasts on screen, my wrapper with the <ToastContainer>
always overlays! Success!
Not so fast, it looks good, but it does not work well. What happens when I want to close the toast?
If the wrapper is an element with popover
, because the element that loads it is a <dialog>
and thanks to this link everything that is not within the subsequently opened <dialog>
becomes inert (yes! even if it's in a higher layer of the top-layer!).
And in the same way, if the wrapper is a <dialog>
(this is what I tried later), for exactly the same reason, I can't click anywhere else but the actions inside the toasts, so the idea of it being a non-blocking message is completely lost.
Therefore, I have reached a dead end where I see several drawbacks:
<dialog>
type, anything else will be inert (and there is no way to change that behavior)In my particular case, the components I use are fully developed by my team, so we can ban the use of <dialog>
and make everything popover elements, and thus have the "solution" to the problem using this workaround. However, I see the future of react-toastify
in danger when the use of <dialog>
begins to generalize within various component libraries!
It occurs to me that we could campaign, among all those interested, to reach the W3C and WHATWG with this problem, proposing several future changes to the standards to avoid this behavior and give the developer more control over these new top-layer elements!
Changes like:
open
event for <dialog>
<dialog>
elements loaded with showModal
do NOT make the rest of the elements inert (even allowing defining a CSS selector for those that should be inert and/or indicating whether it should be all or only those that are below in the top-layer)z-index
property) the elements that load in the top-layerI apologize if I have made any mistakes in my assessments or if I have not considered any options or possibilities. If anyone has any ideas, please help!
@lcoronelp I totally missed the inert issue 😕
I have already started a proposal to allow listening for top layer promotion and being able to change the render order of things in the top layer stack over on WHATWG.
If you like you can raise your concern about inert over there too.
@lcoronelp
In my particular case, the components I use are fully developed by my team, so we can ban the use of
<dialog>
and make everything popover elements,
Did you find a way to simulate a modal using popovers, especially making the background inert? I ask because we are running into the same limitation at Unsplash, so I'm considering a similar workaround to the one you describe.
Do you want to request a feature or report a bug? Feature request
What is the current behavior? Toasts appear over the top of the base layer
What is the expected behavior? Toasts should be elevated to the top layer where possible
With the new Popover API on the horizon it might be worth looking into allowing toasts to be placed in the top-layer. This will prevent toasts from being behind
dialog
s andpopover
elements which, I imagine, will become a problem in the future.Related issues Feature Request: Top Layer Stack Management API to get top layer elements A popover on top of a modal dialog should be interactable