diff --git a/src/atoms/Popper/calculator.ts b/src/atoms/Popper/calculator.ts index 8738ad33..5ba2542e 100644 --- a/src/atoms/Popper/calculator.ts +++ b/src/atoms/Popper/calculator.ts @@ -142,19 +142,6 @@ export const calculateContainerPosition = ( } } - /** - * Adjust if an offset has been set - */ - if (offset) { - if (offset.vertical) { - popoverY += offset.vertical; - } - - if (offset.horizontal) { - popoverX += offset.horizontal; - } - } - /** * Adjust coordinates if user wants to keep element in the viewport */ @@ -176,7 +163,7 @@ export const calculateContainerPosition = ( } } - let contactPoint = 'bottom'; + let isFlipped = false; /** * Flip the positioning when there's not enough space in the viewport */ @@ -191,12 +178,33 @@ export const calculateContainerPosition = ( if (popoverY < 0) { popoverY = anchorEl.top + anchorEl.height; - contactPoint = 'bottom'; + isFlipped = true; } if (popoverY + popoverEl.height > windowHeight) { popoverY = anchorEl.top - popoverEl.height; - contactPoint = 'top'; + isFlipped = true; + } + } + + /** + * Adjust if an offset has been set + */ + if (offset) { + if (offset.vertical) { + if (isFlipped) { + popoverY -= offset.vertical; + } else { + popoverY += offset.vertical; + } + } + + if (offset.horizontal) { + if (isFlipped) { + popoverX -= offset.horizontal; + } else { + popoverX += offset.horizontal; + } } } @@ -205,6 +213,6 @@ export const calculateContainerPosition = ( y: popoverY, width: anchorEl.width, height: popoverEl.height, - contactPoint + isFlipped }; }; diff --git a/src/atoms/Popper/index.tsx b/src/atoms/Popper/index.tsx index d18e8b05..c187bf91 100644 --- a/src/atoms/Popper/index.tsx +++ b/src/atoms/Popper/index.tsx @@ -17,6 +17,7 @@ export interface PopperProps { offset?: Offset; keepInViewPort?: boolean; flip?: boolean; + reactToChange?: number | boolean; width?: string; } @@ -33,7 +34,7 @@ interface CalculatedPosition { y: number; width: number; height: number; - contactPoint: string; + isFlipped: boolean; } const Container = styled.div<{ ref?: any }>` @@ -49,7 +50,8 @@ const Popper: React.SFC = ({ keepInViewPort = false, flip = false, children, - width = 'auto' + reactToChange, + width }) => { const popoverRef = useRef(); const [calculatedPosition, setCalculatedPosition] = useState< @@ -59,7 +61,7 @@ const Popper: React.SFC = ({ y: -10000, width: 0, height: 0, - contactPoint: 'bottom' + isFlipped: false }); const [popoverElRect, setPopoverElRect] = useState({ width: 0, @@ -101,7 +103,7 @@ const Popper: React.SFC = ({ if (popoverRef.current) { setPopoverElRect(getPosition(popoverRef.current)); } - }, [popoverRef]); + }, [popoverRef, reactToChange]); useEffect(() => { updateCalculatedPosition(anchorEl); @@ -118,7 +120,21 @@ const Popper: React.SFC = ({ updateCalculatedPosition(anchorEl); }); - const { y, x, contactPoint, width: anchorElWidth } = calculatedPosition; + const { y, x, isFlipped, width: anchorElWidth } = calculatedPosition; + + if (typeof children === 'function') { + return children({ + ref: popoverRef, + isFlipped, + style: { + top: `${y}px`, + left: `${x}px`, + zIndex: 500, + position: 'fixed', + width: width === 'auto' ? anchorElWidth : width + } + }); + } return ( = ({ style={{ top: `${y}px`, left: `${x}px`, + zIndex: 500, + position: 'fixed', width: width === 'auto' ? anchorElWidth : width }} > - {typeof children === 'function' ? children({ contactPoint }) : children} + {typeof children === 'function' ? children({ isFlipped }) : children} ); }; diff --git a/src/molecules/Select/Options/index.tsx b/src/molecules/Select/Options/index.tsx index 66f7a6fd..d3522e3e 100644 --- a/src/molecules/Select/Options/index.tsx +++ b/src/molecules/Select/Options/index.tsx @@ -28,23 +28,21 @@ interface Props extends OptionsListProps { state?: SelectState; } -const AdvancedMenu = styled(Menu)<{ isOpen: boolean; contactPoint: string }>` - ${({ theme, isOpen, contactPoint }) => +const AdvancedMenu = styled(Menu)<{ isOpen: boolean; isFlipped: boolean }>` + ${({ isOpen, isFlipped }) => isOpen && - contactPoint === 'bottom' && + !isFlipped && css` border-top-left-radius: 0px; border-top-right-radius: 0px; - margin-top: -${theme.borderRadius.default}; `} - ${({ theme, isOpen, contactPoint }) => + ${({ isOpen, isFlipped }) => isOpen && - contactPoint === 'top' && + isFlipped && css` border-bottom-left-radius: 0px; border-bottom-right-radius: 0px; - margin-bottom: -${theme.borderRadius.default}; box-shadow: 0 0px 20px 0 rgba(0, 0, 0, 0.19); `} `; @@ -148,6 +146,7 @@ const Options = ({ ({ vertical: 'top', horizontal: 'left' }} + offset={{ + vertical: -2 + }} width="auto" flip > - {({ contactPoint }: { contactPoint: string }) => ( + {({ + ref, + style, + isFlipped + }: { + ref: any; + style: any; + isFlipped: boolean; + }) => ( diff --git a/storybook/stories/Popper.stories.tsx b/storybook/stories/Popper.stories.tsx index 818b7f8b..3ecbc33d 100644 --- a/storybook/stories/Popper.stories.tsx +++ b/storybook/stories/Popper.stories.tsx @@ -80,7 +80,11 @@ const Example = () => { keepInViewPort={boolean('Keep in viewport?', false)} flip={boolean('Flip', false)} > - I am Sticky + {({ ref, style }: any) => ( + + I am Sticky + + )} );