monday-ui-react-core
Version:
Official monday.com UI resources for application development in React.js
107 lines (82 loc) • 5.44 kB
text/mdx
import { Canvas, Meta } from "@storybook/blocks";
import { ComponentNameDecorator } from "../../components";
import {
DIALOG,
DIALOG_CONTENT_CONTAINER,
DROPDOWN
} from "../../components/related-components/component-description-map";
import * as DropdownInModalsStories from "./dropdown-in-modals.stories";
import { TipKnowIssue } from "./dropdown-in-modals.stories.helpers";
<Meta of={DropdownInModalsStories} />
<ComponentNameDecorator withFoundationBackground>Display dropdowns inside pop-overs</ComponentNameDecorator>
## Problem description
Our dropdowns are implemented using the <Link href="https://react-select.com/home" withoutSpacing>React Select</Link> library.
One of the styling issues with React Select dropdowns is that the menu is not fully displayed when its container has <code>overflow: hidden</code>, <code>overflow: auto</code>, or <code>overflow: scroll</code>.
As a result, when dropdown menus are placed inside a scrolling container or within a Vibe's dialog or modal, the dropdown menu appears damaged, as you can see in the following examples.
<Canvas of={DropdownInModalsStories.ModalWithDamagedDropdown} />
To address this problem, we need to adjust the styling of the dropdown menu to ensure it appears correctly even within these specific container.
We implemented few methods for solving this issue.
## Solution 1: menuPosition = 'fixed'
To handle straightforward scenarios of displaying dropdowns inside a container with relevant overflow styles, you can set <code>menuPosition</code> prop to <code>Dropdown.menuPositions.FIXED</code>.
This prop overrides the dropdown menu's default settings and ensures proper display within the container.
**This solution will work for most cases single select dropdown inside Vibe's Modal or DialogContentContainer, it will not work properly for Vibe's Dialog.**
<Canvas of={DropdownInModalsStories.MenuPosition} />
## Solution 2: insideOverflowContainer
To handle straightforward scenarios of displaying dropdowns inside a container with relevant overflow styles, you can utilize our dropdown's <code>insideOverflowContainer</code> prop.
This prop overrides the dropdown menu's default settings and ensures proper display within the container.
**This solution will work for single select dropdown inside Vibe's Modal or DialogContentContainer cases, it will not work for Vibe's Dialog.**
<TipKnowIssue />
Please note that this solution is intended for the most basic use cases and may not function optimally if your
overflow container has one parent or more with conflicting overflow definitions.
<Canvas of={DropdownInModalsStories.InsideOverflowContainer} />
## Solution 3: insideOverflowWithTransformContainer
The <code>insideOverflowContainer</code> prop will not function as expected for dropdowns displayed inside Vibe's dialog components.
The reason is that Vibe dialogs use CSS transform to position the dialog next to the attached element.
For this specific case, use the 'insideOverflowWithTransformContainer' prop to ensure proper display and functionality.
<TipKnowIssue />
<Canvas of={DropdownInModalsStories.InsideOverflowWithTransformContainer} />
## Solution 4: popupsContainerSelector
For the most complex use cases, you can utilize our dropdown's <code>popupsContainerSelector</code> prop.
This prop allows you to render all the dropdown's popovers in a different node in the DOM, as specified by the provided selector.
This prop will solve all the issues described before and also allow you to control under which DOM element other dropdown containers will render.
To implement this solution and ensure proper display of all dropdown popovers, you need to define a few styles for the container selector, as shown in the following code example:
```css
.container {
top: 0; // Set the container and the beginning of the web page
right: 0; // Set the container and the beginning of the web page
position: "fixed"; // The container should not move when scrolling the web page
width: "100%"; // The container should cover the whole viewport
height: "100%"; // The container should cover the whole viewport
pointerevents: "none"; // The container should not block any event
zindex: 99999; // The container z index should be heigher from the z-index of the modal/dialog which contains the dropdown itself
}
.container * {
pointer-events: auto; // all container children should handle events as usual
}
```
This solution can be useful for multiselection dropdown with single line state, which contains multiple popovers (one for the dropdown menu and one for the selections which hidden under the counter).
If you have defined the dropdown's popovers container styles as required, you can use it as demonstrated in the following example:
```jsx
<div>
<div
id="popovers-container"
style={{
position: "fixed",
width: "100%",
pointerEvents: "none",
zIndex: 99999,
height: "100%",
top: 0,
right: 0
}}
className={styles.pointerEventsAutoToAllChildren}
/>
<Button onClick={() => setShow(true)}>Open Modal</Button>
<Modal id="modal-with-multiple-choice" title="Modal with dropdown" show={show} onClose={closeModal}>
<ModalContent>
<Dropdown multi options={options} popupsContainerSelector="#popovers-container" />
</ModalContent>
</Modal>
</div>
```
<RelatedComponents componentsNames={[DIALOG, DROPDOWN, DIALOG_CONTENT_CONTAINER]} />