Fix edge case in context menu chevron positioning (#7899)

* Fix edge case in context menu chevron positioning

Signed-off-by: Robin Townsend <robin@robin.town>

* Expand context menu positioning regression tests

Signed-off-by: Robin Townsend <robin@robin.town>
This commit is contained in:
Robin 2022-02-25 12:49:57 -05:00 committed by GitHub
parent 3e4e7efd89
commit ece2b8572a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 93 additions and 18 deletions

View file

@ -271,7 +271,7 @@ export default class ContextMenu extends React.PureComponent<IProps, IState> {
windowHeight - contextMenuRect.height - WINDOW_PADDING,
);
if (chevronOffset.top !== undefined) {
chevronOffset.top = props.chevronOffset + props.bottom - position.bottom;
chevronOffset.top = props.chevronOffset + position.bottom - props.bottom;
}
}
if (position.left !== undefined) {
@ -288,7 +288,7 @@ export default class ContextMenu extends React.PureComponent<IProps, IState> {
windowWidth - contextMenuRect.width - WINDOW_PADDING,
);
if (chevronOffset.left !== undefined) {
chevronOffset.left = props.chevronOffset + props.right - position.right;
chevronOffset.left = props.chevronOffset + position.right - props.right;
}
}
}

View file

@ -34,9 +34,59 @@ describe("<ContextMenu />", () => {
height: menuSize,
});
const targetY = windowSize - menuSize + 50;
const targetChevronOffset = 25;
describe("near top edge of window", () => {
const targetY = -50;
const wrapper = mount(
<ContextMenu
bottom={windowSize - targetY - menuSize}
right={menuSize}
chevronFace={ChevronFace.Left}
chevronOffset={targetChevronOffset}
/>,
);
const chevron = wrapper.find(".mx_ContextualMenu_chevron_left");
const actualY = windowSize - parseInt(wrapper.getDOMNode().style.getPropertyValue("bottom")) - menuSize;
const actualChevronOffset = parseInt(chevron.getDOMNode().style.getPropertyValue("top"));
it("stays within the window", () => {
expect(actualY).toBeGreaterThanOrEqual(0);
});
it("positions the chevron correctly", () => {
expect(actualChevronOffset).toEqual(targetChevronOffset + targetY - actualY);
});
});
describe("near right edge of window", () => {
const targetX = windowSize - menuSize + 50;
const wrapper = mount(
<ContextMenu
bottom={0}
left={targetX}
chevronFace={ChevronFace.Top}
chevronOffset={targetChevronOffset}
/>,
);
const chevron = wrapper.find(".mx_ContextualMenu_chevron_top");
const actualX = parseInt(wrapper.getDOMNode().style.getPropertyValue("left"));
const actualChevronOffset = parseInt(chevron.getDOMNode().style.getPropertyValue("left"));
it("stays within the window", () => {
expect(actualX + menuSize).toBeLessThanOrEqual(windowSize);
});
it("positions the chevron correctly", () => {
expect(actualChevronOffset).toEqual(targetChevronOffset + targetX - actualX);
});
});
describe("near bottom edge of window", () => {
const targetY = windowSize - menuSize + 50;
const wrapper = mount(
<ContextMenu
top={targetY}
@ -57,3 +107,28 @@ describe("<ContextMenu />", () => {
expect(actualChevronOffset).toEqual(targetChevronOffset + targetY - actualY);
});
});
describe("near left edge of window", () => {
const targetX = -50;
const wrapper = mount(
<ContextMenu
top={0}
right={windowSize - targetX - menuSize}
chevronFace={ChevronFace.Bottom}
chevronOffset={targetChevronOffset}
/>,
);
const chevron = wrapper.find(".mx_ContextualMenu_chevron_bottom");
const actualX = windowSize - parseInt(wrapper.getDOMNode().style.getPropertyValue("right")) - menuSize;
const actualChevronOffset = parseInt(chevron.getDOMNode().style.getPropertyValue("left"));
it("stays within the window", () => {
expect(actualX).toBeGreaterThanOrEqual(0);
});
it("positions the chevron correctly", () => {
expect(actualChevronOffset).toEqual(targetChevronOffset + targetX - actualX);
});
});
});