Файли
openidea/src/ui/menuAim.test.ts
T
l0ng-ai 4d5de201c4 fix(menu): keep submenus open during diagonal pointer movement (#2153)
Moving the pointer diagonally from a menu item toward its open submenu crossed sibling items, whose hover timers switched or closed the submenu.

While a submenu is open, a sibling hover is deferred when the pointer is inside the triangle from its previous position to the submenu's near corners, including flipped submenus. Stopping on a sibling still switches after 300 ms, moving away keeps the normal delays, and entering the submenu cancels pending switches. This lives in `MenuList`, so every menu and nested level gets it.

Fixes #2128
2026-11-08 21:28:06 +08:00

35 рядки
1.8 KiB
TypeScript

import { describe, expect, it } from "vitest";
import { isSubmenuAim } from "./menuAim";
describe("isSubmenuAim", () => {
const right = { left: 182, right: 362, top: 6, bottom: 150 };
it("accepts diagonal movement toward either near corner and the gap", () => {
expect(isSubmenuAim({ x: 50, y: 20 }, { x: 100, y: 45 }, right)).toBe(true);
expect(isSubmenuAim({ x: 50, y: 80 }, { x: 100, y: 55 }, right)).toBe(true);
expect(isSubmenuAim({ x: 170, y: 40 }, { x: 181, y: 60 }, right)).toBe(true);
expect(isSubmenuAim({ x: 170, y: 40 }, { x: 182, y: 155 }, right)).toBe(true);
});
it("rejects movement away, outside the triangle, or beyond the submenu", () => {
expect(isSubmenuAim({ x: 100, y: 45 }, { x: 60, y: 45 }, right)).toBe(false);
expect(isSubmenuAim({ x: 50, y: 20 }, { x: 60, y: 100 }, right)).toBe(false);
expect(isSubmenuAim({ x: 50, y: 20 }, { x: 50, y: 35 }, right)).toBe(false);
expect(isSubmenuAim({ x: 50, y: 20 }, { x: 400, y: 45 }, right)).toBe(false);
});
it("uses the right edge of a submenu flipped to the left", () => {
const left = { left: 6, right: 180, top: 6, bottom: 150 };
expect(isSubmenuAim({ x: 300, y: 20 }, { x: 250, y: 45 }, left)).toBe(true);
expect(isSubmenuAim({ x: 250, y: 45 }, { x: 300, y: 45 }, left)).toBe(false);
});
it("rejects a first move, a stationary pointer and degenerate triangles", () => {
expect(isSubmenuAim(null, { x: 100, y: 45 }, right)).toBe(false);
expect(isSubmenuAim({ x: 50, y: 20 }, { x: 50, y: 20 }, right)).toBe(false);
expect(isSubmenuAim({ x: 182, y: 20 }, { x: 182, y: 45 }, right)).toBe(false);
expect(isSubmenuAim({ x: 200, y: 20 }, { x: 210, y: 45 }, right)).toBe(false);
expect(isSubmenuAim({ x: 50, y: 20 }, { x: 100, y: 45 }, { ...right, bottom: 6 })).toBe(false);
});
});