Skip to content

Commit

Permalink
fix(webapp): don't render popover outside the visible window (#1534)
Browse files Browse the repository at this point in the history
  • Loading branch information
eh-am committed Sep 22, 2022
1 parent 740a0f7 commit 0ce4e7d
Showing 1 changed file with 54 additions and 8 deletions.
62 changes: 54 additions & 8 deletions webapp/javascript/ui/Popover.tsx
@@ -1,4 +1,11 @@
import React, { SetStateAction, Dispatch, ReactNode } from 'react';
import React, {
useRef,
useState,
useLayoutEffect,
SetStateAction,
Dispatch,
ReactNode,
} from 'react';
import classnames from 'classnames';
import OutsideClickHandler from 'react-outside-click-handler';
import styles from './Popover.module.scss';
Expand All @@ -23,16 +30,29 @@ export function Popover({
children,
anchorPoint,
}: PopoverProps) {
// TODO(eh-am): handle out of bounds positioning
const popoverPosition = {
left: `${anchorPoint.x}px`,
top: `${anchorPoint.y}px`,
position: 'absolute' as const,
};
const popoverRef = useRef<HTMLDivElement>(null);
const [popoverPosition, setPopoverPosition] = useState<React.CSSProperties>({
display: 'hidden',
});

useLayoutEffect(() => {
if (isModalOpen && popoverRef.current) {
const pos = getPopoverPosition(
popoverRef.current.clientWidth,
window.innerWidth,
anchorPoint
);
setPopoverPosition(pos);
}
}, [isModalOpen]);

return (
<OutsideClickHandler onOutsideClick={() => setModalOpenStatus(false)}>
<div className={styles.container} style={popoverPosition}>
<div
className={styles.container}
style={popoverPosition}
ref={popoverRef}
>
{isModalOpen && (
<div className={classnames(styles.popover, className)}>
{children}
Expand All @@ -43,6 +63,32 @@ export function Popover({
);
}

function getPopoverPosition(
popoverWidth: number,
windowWidth: number,
anchorPoint: PopoverProps['anchorPoint']
) {
// Give some room between popover end and the window edge
const marginToWindowEdge = 30;
const defaultProps = {
top: `${anchorPoint.y}px`,
position: 'absolute' as const,
};

if (anchorPoint.x + popoverWidth + marginToWindowEdge >= windowWidth) {
// position to the left
return {
...defaultProps,
left: `${anchorPoint.x - popoverWidth}px`,
};
}

// position to the right
return {
...defaultProps,
left: `${anchorPoint.x}px`,
};
}
interface PopoverMemberProps {
children: ReactNode;
}
Expand Down

0 comments on commit 0ce4e7d

Please sign in to comment.