diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 9ca3516f8..931ede6b4 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 d72b1bdd3..4e6f5fedf 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 5d3792cc5..691dfeac7 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'; - + # 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 d364d3542..2d0e3af1d 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, @@ -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(-1); + let targetRef = useRef(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 ? (
- {getPopoverContent - ? getPopoverContent(overflowedItems) + {dropdownContent + ? dropdownContent(overflowedItems) : overflowedItems.map(item => item.element)}
) : 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)} {popoverContent && ( - setPopoverVisible(visible)} - placement="bottom" - > - - + ::-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}; + } + } + `} + /> + setPopoverVisible(visible)} + placement="bottom" + > + + + )} );