Dynamically provide portal container element for modal components #7313
jonahschueller
started this conversation in
Ideas
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
-
General
There have been many bug reports and discussions that
shadcn/ui
does not always handle nesting complex modal components correctly, e.g. opening aPopover
inside of aSheet
might close theSheet
upon interaction with thePopover
as it is hoisted to thedocument.body
. I will not file yet anotherbug
description, but propose a potential solution to this issue.This behaviour occurs because
shadcn/ui
falls back to the default behaviour ofradix-ui
, which is to make use ofdocument.body
as the default portal container.In the project I am currently working on the user can toggle the main page in to browser fullscreen.
When doing that, components like
Dropdown
are no longer visible to the user because they are appended to thedocument.body
, but only the main page is visible.I implemented a custom workaround, which I think could serve as some food for thought for an official solution:
Solution description
To fix this issue, I had to ensure that the
portal container
which is used by the mentioned components dynamically adjusts to the component it is wrapped in. For example, when aPopover
is used at the root level it should usedocument.body
, but if it is used inside of aSheet
it should refer to a<div>
which is inside of theSheet
in order to prevent events outside of the sheet container.This led me to:
React Context API
I added a custom
PortalContainerContext
which holds theHTMLElement
which should be used as the portal container byradix-ui
.Additionally, I adjusted the
shadcn/ui
components to fetch the portal container from the current context. When using e.g. aSheet
I wrap my sheet content into aPortalContainerProvider
which will set the portal container of all components inside of the sheet, preventing the closing behaviour described previously.This way I can dynamically adjust which element is used as the anchor point for various components.
Since I didn't wanted to make the
PortalContainerContext
a mandatory context in my app, it makes use of a default value ofdocument.body
. Therefore, it will behave as usual in all situations where noPortalContainerContext
is given, but hook into a custom container, once provided.Why should this be in
shadcn/ui
Although, this solution can be implemented fairly easily, it still requires adjustment of every modal type shadcn component.
Additionally, one could argue that e.g. a
Sheet
should automatically provide this anchor by default to hide this functionality from the user.Alternative solutions
I think the minimum viable solution could also include to expose the
container
property of theradix-ui Portals
to the user of the component. This way, no adjustment of the components itself are needed.Uncertainties / TBD
Although I have tested this solution in my specific use case (e.g. in
Sheets
or browser fullscreen) I am not sure if a) it fixes all of these types of issues I haven't encountered in my use case & b) is always the expected behaviour. For example for modal type like<Alert />
or<Dialog />
.A more advanced solutions (e.g. with multiple anchor points for different components) might be required to meet all requirements of all components.
Nevertheless, I think something like this would make a nice addition to
shadcn/ui
:)Beta Was this translation helpful? Give feedback.
All reactions