This is an automated email from the ASF dual-hosted git repository.

diegopucci pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/superset.git


The following commit(s) were added to refs/heads/master by this push:
     new afc10a247b feat: Adds overflow to the DropdownContainer popover 
(#22250)
afc10a247b is described below

commit afc10a247b1ab736ffb888047ec3c3a3b995ecc0
Author: Michael S. Molina <[email protected]>
AuthorDate: Thu Dec 1 06:24:02 2022 -0500

    feat: Adds overflow to the DropdownContainer popover (#22250)
---
 .github/CODEOWNERS                                 |   1 +
 .../DropdownContainer.stories.tsx                  |   2 +-
 .../DropdownContainer/Overview.stories.mdx         |   4 +-
 .../src/components/DropdownContainer/index.tsx     | 137 ++++++++++++++-------
 4 files changed, 98 insertions(+), 46 deletions(-)

diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
index 9ca3516f8f..931ede6b48 100644
--- a/.github/CODEOWNERS
+++ b/.github/CODEOWNERS
@@ -14,6 +14,7 @@
 
 /superset-frontend/src/components/Select/ @michael-s-molina @geido @ktmud
 /superset-frontend/src/components/MetadataBar/ @michael-s-molina
+/superset-frontend/src/components/DropdownContainer/ @michael-s-molina
 
 # Notify Helm Chart maintainers about changes in it
 
diff --git 
a/superset-frontend/src/components/DropdownContainer/DropdownContainer.stories.tsx
 
b/superset-frontend/src/components/DropdownContainer/DropdownContainer.stories.tsx
index d72b1bdd39..4e6f5fedfd 100644
--- 
a/superset-frontend/src/components/DropdownContainer/DropdownContainer.stories.tsx
+++ 
b/superset-frontend/src/components/DropdownContainer/DropdownContainer.stories.tsx
@@ -24,7 +24,7 @@ import Button from '../Button';
 import DropdownContainer, { DropdownContainerProps, Ref } from '.';
 
 export default {
-  title: 'DropdownContainer',
+  title: 'Design System/Components/DropdownContainer',
   component: DropdownContainer,
 };
 
diff --git 
a/superset-frontend/src/components/DropdownContainer/Overview.stories.mdx 
b/superset-frontend/src/components/DropdownContainer/Overview.stories.mdx
index 5d3792cc5f..691dfeac73 100644
--- a/superset-frontend/src/components/DropdownContainer/Overview.stories.mdx
+++ b/superset-frontend/src/components/DropdownContainer/Overview.stories.mdx
@@ -1,6 +1,6 @@
 import { Meta, Source } from '@storybook/addon-docs';
 
-<Meta title="DropdownContainer/Overview" />
+<Meta title="Design System/Components/DropdownContainer/Overview" />
 
 # Usage
 
@@ -14,4 +14,4 @@ the available width, they are displayed vertically in a 
dropdown. Some of the co
 
 The component accepts any React element which ensures a high level of 
variability in Superset.
 
-To check the component in detail and its interactions, check the 
[DropdownContainer](/story/dropdowncontainer--component) page.
+To check the component in detail and its interactions, check the 
[DropdownContainer](/story/design-system-components-dropdowncontainer--component)
 page.
diff --git a/superset-frontend/src/components/DropdownContainer/index.tsx 
b/superset-frontend/src/components/DropdownContainer/index.tsx
index d364d3542e..2d0e3af1d6 100644
--- a/superset-frontend/src/components/DropdownContainer/index.tsx
+++ b/superset-frontend/src/components/DropdownContainer/index.tsx
@@ -26,7 +26,9 @@ import React, {
   useLayoutEffect,
   useMemo,
   useState,
+  useRef,
 } from 'react';
+import { Global } from '@emotion/react';
 import { css, t, useTheme } from '@superset-ui/core';
 import { useResizeDetector } from 'react-resize-detector';
 import { usePrevious } from 'src/hooks/usePrevious';
@@ -35,6 +37,8 @@ import Icons from '../Icons';
 import Button from '../Button';
 import Popover from '../Popover';
 
+const MAX_HEIGHT = 500;
+
 /**
  * Container item.
  */
@@ -104,12 +108,12 @@ const DropdownContainer = forwardRef(
     {
       items,
       onOverflowingStateChange,
-      dropdownContent: getPopoverContent,
-      dropdownRef: popoverRef,
-      dropdownStyle: popoverStyle = {},
-      dropdownTriggerCount: popoverTriggerCount,
-      dropdownTriggerIcon: popoverTriggerIcon,
-      dropdownTriggerText: popoverTriggerText = t('More'),
+      dropdownContent,
+      dropdownRef,
+      dropdownStyle = {},
+      dropdownTriggerCount,
+      dropdownTriggerIcon,
+      dropdownTriggerText = t('More'),
       style,
     }: DropdownContainerProps,
     outerRef: RefObject<Ref>,
@@ -124,6 +128,13 @@ const DropdownContainer = forwardRef(
     // We use React.useState to be able to mock the state in Jest
     const [overflowingIndex, setOverflowingIndex] = React.useState<number>(-1);
 
+    let targetRef = useRef<HTMLDivElement>(null);
+    if (dropdownRef) {
+      targetRef = dropdownRef;
+    }
+
+    const [showOverflow, setShowOverflow] = useState(false);
+
     useLayoutEffect(() => {
       const container = current?.children.item(0);
       if (container) {
@@ -214,7 +225,7 @@ const DropdownContainer = forwardRef(
 
     const popoverContent = useMemo(
       () =>
-        getPopoverContent || overflowingCount ? (
+        dropdownContent || overflowingCount ? (
           <div
             css={css`
               display: flex;
@@ -222,24 +233,36 @@ const DropdownContainer = forwardRef(
               gap: ${theme.gridUnit * 4}px;
             `}
             data-test="dropdown-content"
-            style={popoverStyle}
-            ref={popoverRef}
+            style={dropdownStyle}
+            ref={targetRef}
           >
-            {getPopoverContent
-              ? getPopoverContent(overflowedItems)
+            {dropdownContent
+              ? dropdownContent(overflowedItems)
               : overflowedItems.map(item => item.element)}
           </div>
         ) : null,
       [
-        getPopoverContent,
-        overflowedItems,
+        dropdownContent,
         overflowingCount,
-        popoverRef,
-        popoverStyle,
         theme.gridUnit,
+        dropdownStyle,
+        overflowedItems,
       ],
     );
 
+    useLayoutEffect(() => {
+      if (popoverVisible) {
+        // Measures scroll height after rendering the elements
+        setTimeout(() => {
+          if (targetRef.current) {
+            // We only set overflow when there's enough space to display
+            // Select's popovers because they are restrained by the overflow 
property.
+            setShowOverflow(targetRef.current.scrollHeight > MAX_HEIGHT);
+          }
+        }, 100);
+      }
+    }, [popoverVisible]);
+
     useImperativeHandle(
       outerRef,
       () => ({
@@ -271,35 +294,63 @@ const DropdownContainer = forwardRef(
           {notOverflowedItems.map(item => item.element)}
         </div>
         {popoverContent && (
-          <Popover
-            content={popoverContent}
-            trigger="click"
-            visible={popoverVisible}
-            onVisibleChange={visible => setPopoverVisible(visible)}
-            placement="bottom"
-          >
-            <Button buttonStyle="secondary">
-              {popoverTriggerIcon}
-              {popoverTriggerText}
-              <Badge
-                count={popoverTriggerCount ?? overflowingCount}
-                css={css`
-                  margin-left: ${popoverTriggerCount ?? overflowingCount
-                    ? '8px'
-                    : '0'};
-                `}
-              />
-              <Icons.DownOutlined
-                iconSize="m"
-                iconColor={theme.colors.grayscale.light1}
-                css={css`
-                  .anticon {
-                    display: flex;
+          <>
+            <Global
+              styles={css`
+                .ant-popover-inner-content {
+                  max-height: ${MAX_HEIGHT}px;
+                  overflow: ${showOverflow ? 'auto' : 'visible'};
+                  padding: ${theme.gridUnit * 3}px ${theme.gridUnit * 4}px;
+
+                  // Some OS versions only show the scroll when hovering.
+                  // These settings will make the scroll always visible.
+                  ::-webkit-scrollbar {
+                    -webkit-appearance: none;
+                    width: 14px;
+                  }
+                  ::-webkit-scrollbar-thumb {
+                    border-radius: 9px;
+                    background-color: ${theme.colors.grayscale.light1};
+                    border: 3px solid transparent;
+                    background-clip: content-box;
+                  }
+                  ::-webkit-scrollbar-track {
+                    background-color: ${theme.colors.grayscale.light4};
+                    border-left: 1px solid ${theme.colors.grayscale.light2};
                   }
-                `}
-              />
-            </Button>
-          </Popover>
+                }
+              `}
+            />
+            <Popover
+              content={popoverContent}
+              trigger="click"
+              visible={popoverVisible}
+              onVisibleChange={visible => setPopoverVisible(visible)}
+              placement="bottom"
+            >
+              <Button buttonStyle="secondary">
+                {dropdownTriggerIcon}
+                {dropdownTriggerText}
+                <Badge
+                  count={dropdownTriggerCount ?? overflowingCount}
+                  css={css`
+                    margin-left: ${dropdownTriggerCount ?? overflowingCount
+                      ? `${theme.gridUnit * 2}px`
+                      : '0'};
+                  `}
+                />
+                <Icons.DownOutlined
+                  iconSize="m"
+                  iconColor={theme.colors.grayscale.light1}
+                  css={css`
+                    .anticon {
+                      display: flex;
+                    }
+                  `}
+                />
+              </Button>
+            </Popover>
+          </>
         )}
       </div>
     );

Reply via email to