Skip to content

Commit 71b1de2

Browse files
Scott DoverScott Dover
authored andcommitted
chore: finish up menu positioning
Signed-off-by: Scott Dover <[email protected]>
1 parent e4ae951 commit 71b1de2

File tree

1 file changed

+33
-19
lines changed

1 file changed

+33
-19
lines changed

client/src/webview/ColumnHeaderMenu.tsx

Lines changed: 33 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -29,14 +29,14 @@ const GridMenu = ({
2929
top,
3030
left: incomingLeft,
3131
subMenu,
32-
subtractWidthFromLeft,
32+
parentDimensions,
3333
}: {
3434
menuItems: (MenuItem | string)[];
3535
theme: string;
3636
top: number;
37-
left: number;
37+
left?: number;
3838
subMenu?: boolean;
39-
subtractWidthFromLeft?: boolean;
39+
parentDimensions?: { left: number; width: number };
4040
}) => {
4141
const menuRef = useRef<HTMLDivElement>(undefined);
4242
const [subMenuItems, setSubMenuItems] = useState<(MenuItem | string)[]>([]);
@@ -45,18 +45,27 @@ const GridMenu = ({
4545
: `ag-menu ag-column-menu ag-ltr ag-popup-child ag-popup-positioned-under ${theme}`;
4646
const [activeIndex, setActiveIndex] = useState(-1);
4747

48-
const [offset, setOffset] = useState(0);
49-
const [left, setLeft] = useState(incomingLeft);
48+
const [left, setLeft] = useState(parentDimensions?.left ?? incomingLeft);
49+
const [displayed, setDisplayed] = useState(false);
5050
useEffect(() => {
51-
const w = menuRef.current.getBoundingClientRect().width;
52-
const cw = menuRef.current.closest("body").clientWidth;
53-
if (subtractWidthFromLeft) {
54-
setLeft(incomingLeft - w);
51+
const clientWidth = menuRef.current.closest("body").clientWidth;
52+
const width = menuRef.current.getBoundingClientRect().width;
53+
54+
if (parentDimensions) {
55+
// First, lets put the child menu to the right
56+
let adjustedLeft = parentDimensions.left + parentDimensions.width;
57+
// If that's off screen, lets instead place it to the left
58+
if (adjustedLeft + width > clientWidth) {
59+
adjustedLeft = parentDimensions.left - width;
60+
}
61+
setLeft(adjustedLeft);
62+
setDisplayed(true);
5563
return;
5664
}
57-
if (left + w > cw) {
58-
setOffset(left + w - cw + 15);
65+
if (left + width > clientWidth) {
66+
setLeft(left - (left + width - clientWidth + 15));
5967
}
68+
setDisplayed(true);
6069
}, []);
6170

6271
return (
@@ -66,20 +75,25 @@ const GridMenu = ({
6675
menuItems={subMenuItems}
6776
theme={theme}
6877
top={top}
69-
left={
70-
offset === 0
71-
? left + menuRef.current.getBoundingClientRect().width
72-
: left - offset
73-
}
74-
subtractWidthFromLeft={offset !== 0}
78+
parentDimensions={{
79+
left,
80+
width: menuRef.current.getBoundingClientRect().width,
81+
}}
7582
subMenu
7683
/>
7784
)}
78-
<div className="ag-theme-sas ag-popup">
85+
<div
86+
className="ag-theme-sas ag-popup"
87+
// We rely on the menu being displayed _first_ before being able to
88+
// calculate it's correct left position. This prevents actually showing the
89+
// menu to the user until we've figured that out. This prevents flashes of the
90+
// menu in the wrong position.
91+
style={{ visibility: displayed ? "visible" : "hidden" }}
92+
>
7993
<div
8094
className={className}
8195
role="presentation"
82-
style={{ top, left: left - offset }}
96+
style={{ top, left }}
8397
ref={menuRef}
8498
>
8599
<div className="ag-menu-list ag-focus-managed" role="menu">

0 commit comments

Comments
 (0)