ensure contextMenu doesn't overflow viewport (#364)
This commit is contained in:
parent
d2a3ed7931
commit
8104c8525d
@ -18,7 +18,12 @@ type Props = {
|
|||||||
|
|
||||||
function ContextMenu({ options, onCloseRequest, top, left }: Props) {
|
function ContextMenu({ options, onCloseRequest, top, left }: Props) {
|
||||||
return (
|
return (
|
||||||
<Popover onCloseRequest={onCloseRequest} top={top} left={left}>
|
<Popover
|
||||||
|
onCloseRequest={onCloseRequest}
|
||||||
|
top={top}
|
||||||
|
left={left}
|
||||||
|
fitInViewport={true}
|
||||||
|
>
|
||||||
<ul className="context-menu" onContextMenu={e => e.preventDefault()}>
|
<ul className="context-menu" onContextMenu={e => e.preventDefault()}>
|
||||||
{options.map((option, idx) => (
|
{options.map((option, idx) => (
|
||||||
<li
|
<li
|
||||||
|
@ -1,15 +1,41 @@
|
|||||||
import React from "react";
|
import React, { useLayoutEffect, useRef } from "react";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
top?: number;
|
top?: number;
|
||||||
left?: number;
|
left?: number;
|
||||||
children?: React.ReactNode;
|
children?: React.ReactNode;
|
||||||
onCloseRequest?(): void;
|
onCloseRequest?(): void;
|
||||||
|
fitInViewport?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export function Popover({ children, left, onCloseRequest, top }: Props) {
|
export function Popover({
|
||||||
|
children,
|
||||||
|
left,
|
||||||
|
top,
|
||||||
|
onCloseRequest,
|
||||||
|
fitInViewport = false
|
||||||
|
}: Props) {
|
||||||
|
const popoverRef = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
|
// ensure the popover doesn't overflow the viewport
|
||||||
|
useLayoutEffect(() => {
|
||||||
|
if (fitInViewport && popoverRef.current) {
|
||||||
|
const element = popoverRef.current;
|
||||||
|
const { x, y, width, height } = element.getBoundingClientRect();
|
||||||
|
|
||||||
|
const viewportWidth = window.innerWidth;
|
||||||
|
if (x + width > viewportWidth) {
|
||||||
|
element.style.left = viewportWidth - width + "px";
|
||||||
|
}
|
||||||
|
const viewportHeight = window.innerHeight;
|
||||||
|
if (y + height > viewportHeight) {
|
||||||
|
element.style.top = viewportHeight - height + "px";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, [fitInViewport]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="popover" style={{ top: top, left: left }}>
|
<div className="popover" style={{ top: top, left: left }} ref={popoverRef}>
|
||||||
<div
|
<div
|
||||||
className="cover"
|
className="cover"
|
||||||
onClick={onCloseRequest}
|
onClick={onCloseRequest}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user