X-Git-Url: https://git.arvados.org/arvados.git/blobdiff_plain/3456de80d25dfb480133bd8afd9f51cdb1d942ee..562687ce72e709d485aa47773117a51a764a6606:/services/workbench2/src/components/multiselect-toolbar/ms-toolbar-overflow-wrapper.tsx diff --git a/services/workbench2/src/components/multiselect-toolbar/ms-toolbar-overflow-wrapper.tsx b/services/workbench2/src/components/multiselect-toolbar/ms-toolbar-overflow-wrapper.tsx index e63225b05f..5c1c433712 100644 --- a/services/workbench2/src/components/multiselect-toolbar/ms-toolbar-overflow-wrapper.tsx +++ b/services/workbench2/src/components/multiselect-toolbar/ms-toolbar-overflow-wrapper.tsx @@ -4,9 +4,9 @@ import React, { useState, useRef, useEffect } from 'react'; import { StyleRulesCallback, WithStyles, withStyles } from '@material-ui/core'; -import classnames from 'classnames' +import classnames from 'classnames'; import { ArvadosTheme } from 'common/custom-theme'; -import { OverflowMenu } from './ms-toolbar-overflow-menu'; +import { OverflowMenu, OverflowChild } from './ms-toolbar-overflow-menu'; type CssRules = 'visible' | 'inVisible' | 'toolbarWrapper' | 'overflowStyle'; @@ -24,27 +24,35 @@ const styles: StyleRulesCallback = (theme: ArvadosTheme) => ({ toolbarWrapper: { display: 'flex', overflow: 'hidden', - padding: '0 20px', + padding: '0 0px 0 20px', width: '100%', }, overflowStyle: { order: 99, position: 'sticky', right: '-2rem', - backgroundColor: 'white', + width: 0, }, }); -export const IntersectionObserverWrapper = withStyles(styles)((props: any & WithStyles) => { - const { classes, children} = props +type WrapperProps = { + children: OverflowChild[]; + menuLength: number; +}; +export const IntersectionObserverWrapper = withStyles(styles)((props: WrapperProps & WithStyles) => { + const { classes, children, menuLength } = props; + const lastEntryId = (children[menuLength - 1] as any).props['data-targetid']; const navRef = useRef(null); - const [visibilityMap, setVisibilityMap] = useState({}); - + const [visibilityMap, setVisibilityMap] = useState>({}); + const [numHidden, setNumHidden] = useState(() => findNumHidden(visibilityMap)); + const prevNumHidden = useRef(numHidden); + const handleIntersection = (entries) => { - const updatedEntries = {}; + const updatedEntries: Record = {}; entries.forEach((entry) => { - const targetid = entry.target.dataset.targetid; + const targetid = entry.target.dataset.targetid as string; + //if true, the element is visible if (entry.isIntersecting) { updatedEntries[targetid] = true; } else { @@ -55,12 +63,30 @@ export const IntersectionObserverWrapper = withStyles(styles)((props: any & With setVisibilityMap((prev) => ({ ...prev, ...updatedEntries, + [lastEntryId]: Object.keys(updatedEntries)[0] === lastEntryId, })); }; + + //ensures that the last element is always visible if the second to last is visible + useEffect(() => { + if ((prevNumHidden.current > 1 || prevNumHidden.current === 0) && numHidden === 1) { + setVisibilityMap((prev) => ({ + ...prev, + [lastEntryId]: true, + })); + } + prevNumHidden.current = numHidden; + }, [numHidden, lastEntryId]); + + useEffect(() => { + setNumHidden(findNumHidden(visibilityMap)); + }, [visibilityMap]); + useEffect((): any => { + setVisibilityMap({}); const observer = new IntersectionObserver(handleIntersection, { root: navRef.current, - rootMargin: '0px -20px 0px 0px', + rootMargin: '0px -30px 0px 0px', threshold: 1, }); // We are adding observers to child elements of the container div @@ -75,24 +101,34 @@ export const IntersectionObserverWrapper = withStyles(styles)((props: any & With return () => { observer.disconnect(); }; - }, []); + // eslint-disable-next-line + }, [menuLength]); + + function findNumHidden(visMap: {}) { + return Object.values(visMap).filter((x) => x === false).length; + } return ( -
- {React.Children.map(children, (child) => { - return React.cloneElement(child, { - className: classnames(child.props.className, { - [classes.visible]: !!visibilityMap[child.props["data-targetid"]], - [classes.inVisible]: !visibilityMap[child.props["data-targetid"]] - }) - }); - })} - - {children} - -
+
+ {React.Children.map(children, (child) => { + return React.cloneElement(child, { + className: classnames(child.props.className, { + [classes.visible]: !!visibilityMap[child.props['data-targetid']], + [classes.inVisible]: !visibilityMap[child.props['data-targetid']], + }), + }); + })} + {numHidden >= 2 && ( + + {children.filter((child) => !child.props['data-targetid'].includes("Divider"))} + + )} +
); });