Dynamically provide portal container element for modal components #7313
jonahschueller
started this conversation in
Ideas
Replies: 1 comment 1 reply
-
|
We ran into this exact (or almost identical issue) — a bottom Sheet covering our sidebar layout because it portals to See #9964 The change is ~3 lines per component and fully backwards-compatible (defaults to |
Beta Was this translation helpful? Give feedback.
1 reply
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/uidoes not always handle nesting complex modal components correctly, e.g. opening aPopoverinside of aSheetmight close theSheetupon interaction with thePopoveras it is hoisted to thedocument.body. I will not file yet anotherbugdescription, but propose a potential solution to this issue.This behaviour occurs because
shadcn/uifalls back to the default behaviour ofradix-ui, which is to make use ofdocument.bodyas 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
Dropdownare 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 containerwhich is used by the mentioned components dynamically adjusts to the component it is wrapped in. For example, when aPopoveris used at the root level it should usedocument.body, but if it is used inside of aSheetit should refer to a<div>which is inside of theSheetin order to prevent events outside of the sheet container.This led me to:
React Context APII added a custom
PortalContainerContextwhich holds theHTMLElementwhich should be used as the portal container byradix-ui.Additionally, I adjusted the
shadcn/uicomponents to fetch the portal container from the current context. When using e.g. aSheetI wrap my sheet content into aPortalContainerProviderwhich 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
PortalContainerContexta mandatory context in my app, it makes use of a default value ofdocument.body. Therefore, it will behave as usual in all situations where noPortalContainerContextis given, but hook into a custom container, once provided.Why should this be in
shadcn/uiAlthough, 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
Sheetshould 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
containerproperty of theradix-ui Portalsto 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
Sheetsor 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