Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Popover API and top-layer support #959

Open
Link2Twenty opened this issue May 16, 2023 · 7 comments
Open

Popover API and top-layer support #959

Link2Twenty opened this issue May 16, 2023 · 7 comments
Labels

Comments

@Link2Twenty
Copy link

Link2Twenty commented May 16, 2023

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 dialogs and popover 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

@fkhadra fkhadra added the future label May 18, 2023
@andelkocvjetkovic
Copy link

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.

@Link2Twenty
Copy link
Author

Link2Twenty commented Mar 5, 2024

Just a gentle prompt that popover will be in all browsers when Firefox 126 is released which is scheduled for 2024-05-14.

@lcoronelp
Copy link

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.

@Link2Twenty
Copy link
Author

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.

https://x.com/bramus/status/1764979592077381641

@lcoronelp
Copy link

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:

  • As long as there are elements in the top-layer of the <dialog> type, anything else will be inert (and there is no way to change that behavior)
  • You can't define the Z-axis position of elements in the top-layer (which would be super useful)
  • I think the standard should be (if you can't control making everything else inert or not) to make everything else inert EXCEPT what's above in the top-layer! (this already happens between dialogs, why not with the rest of the popover elements?)

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:

  • An open event for <dialog>
  • A way to indicate that <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)
  • A way to order (I vote for using the z-index property) the elements that load in the top-layer

I 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!

@Link2Twenty
Copy link
Author

@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.

@OliverJAsh
Copy link

@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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

5 participants