Skip to content

Commit

Permalink
Merge pull request #252 from sofarsounds/develop
Browse files Browse the repository at this point in the history
v7.1.2
  • Loading branch information
David Floegel authored Feb 17, 2020
2 parents 40a8413 + 41d73c6 commit 7ea5032
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 33 deletions.
42 changes: 25 additions & 17 deletions src/atoms/Popper/calculator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
*/
Expand All @@ -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
*/
Expand All @@ -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;
}
}
}

Expand All @@ -205,6 +213,6 @@ export const calculateContainerPosition = (
y: popoverY,
width: anchorEl.width,
height: popoverEl.height,
contactPoint
isFlipped
};
};
30 changes: 24 additions & 6 deletions src/atoms/Popper/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export interface PopperProps {
offset?: Offset;
keepInViewPort?: boolean;
flip?: boolean;
reactToChange?: number | boolean;
width?: string;
}

Expand All @@ -33,7 +34,7 @@ interface CalculatedPosition {
y: number;
width: number;
height: number;
contactPoint: string;
isFlipped: boolean;
}

const Container = styled.div<{ ref?: any }>`
Expand All @@ -49,7 +50,8 @@ const Popper: React.SFC<Props> = ({
keepInViewPort = false,
flip = false,
children,
width = 'auto'
reactToChange,
width
}) => {
const popoverRef = useRef<HTMLDivElement>();
const [calculatedPosition, setCalculatedPosition] = useState<
Expand All @@ -59,7 +61,7 @@ const Popper: React.SFC<Props> = ({
y: -10000,
width: 0,
height: 0,
contactPoint: 'bottom'
isFlipped: false
});
const [popoverElRect, setPopoverElRect] = useState<PopoverDomEl>({
width: 0,
Expand Down Expand Up @@ -101,7 +103,7 @@ const Popper: React.SFC<Props> = ({
if (popoverRef.current) {
setPopoverElRect(getPosition(popoverRef.current));
}
}, [popoverRef]);
}, [popoverRef, reactToChange]);

useEffect(() => {
updateCalculatedPosition(anchorEl);
Expand All @@ -118,18 +120,34 @@ const Popper: React.SFC<Props> = ({
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 (
<Container
ref={popoverRef}
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}
</Container>
);
};
Expand Down
30 changes: 21 additions & 9 deletions src/molecules/Select/Options/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,23 +28,21 @@ interface Props<T> extends OptionsListProps<T> {
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);
`}
`;
Expand Down Expand Up @@ -148,6 +146,7 @@ const Options = <T extends {}>({
<Portal dom={document.body}>
<Popper
anchorEl={innerRef}
reactToChange={options.length}
anchorOrigin={{
vertical: 'bottom',
horizontal: 'left'
Expand All @@ -156,13 +155,26 @@ const Options = <T extends {}>({
vertical: 'top',
horizontal: 'left'
}}
offset={{
vertical: -2
}}
width="auto"
flip
>
{({ contactPoint }: { contactPoint: string }) => (
{({
ref,
style,
isFlipped
}: {
ref: any;
style: any;
isFlipped: boolean;
}) => (
<AdvancedMenu
ref={ref}
style={style}
isOpen={isOpen}
contactPoint={contactPoint}
isFlipped={isFlipped}
bordered
data-qaid={`${qaId}-${showPopularOptions ? 'popular' : 'menu'}`}
>
Expand Down
6 changes: 5 additions & 1 deletion storybook/stories/Popper.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,11 @@ const Example = () => {
keepInViewPort={boolean('Keep in viewport?', false)}
flip={boolean('Flip', false)}
>
<StickyStyle>I am Sticky</StickyStyle>
{({ ref, style }: any) => (
<StickyStyle ref={ref} style={style}>
I am Sticky
</StickyStyle>
)}
</Popper>
</div>
);
Expand Down

0 comments on commit 7ea5032

Please sign in to comment.