Every menu with a submenu has this bug. You open it, aim at something near the bottom, and it shuts on you halfway there. So you learn to move sideways first and then down, in an L, like you are defusing a bomb. Nobody taught you that.
Two menus below. Identical rows, identical submenu. One of them has a fix in it.
Open Move to in both boxes, then take one diagonal straight at Trash. Do not stop on the way and do not go sideways first.
the fix
Your cursor crossed Copy link and Add label on the way. Those are real hovers, and a menu that answers them closes the submenu, because that is what pointing at another row means. The bug is that being right about each event adds up to being wrong about the hand.
So while the cursor is on its way to the submenu, the rows it crosses stop counting. On its way is a triangle: the point it left the row, and the submenu's near edge. Three cross products decide whether a point is inside it.
const side = (a: Point, b: Point, p: Point) =>
(b.x - a.x) * (p.y - a.y) - (b.y - a.y) * (p.x - a.x);
export function inGrace(p: Point, g: Grace): boolean {
const a = side(g.from, g.top, p);
const b = side(g.top, g.bottom, p);
const c = side(g.bottom, g.from, p);
return (a >= 0 && b >= 0 && c >= 0) || (a <= 0 && b <= 0 && c <= 0);
}
It has a name. Ben Kamens reverse-engineered it out of Amazon's mega dropdown in 2013 and shipped it as a jQuery plugin called menu-aim, and it is usually called a safe triangle. You will also see safe area, safe polygon, or Amazon's own prediction cone. Component libraries tend to say polygon rather than triangle, because a submenu that can open above or below its trigger needs more than three points. Ours only opens to the right, so three is enough. None of it is new: hierarchical menus on the Mac were doing this in the mid-eighties.
Do not confuse it with hover intent, which is the other family and the one this post is arguing against. Those measure how long or how fast you have hovered. Same problem, opposite signal.
The usual answer instead is a timer, three hundred milliseconds before anything closes, and it is worse in both directions: it shuts on you if you pause to read a label, and it hangs around after you have plainly left. Time is not the signal. Direction is, and a timer cannot see direction.
- Rename
- Duplicate
- Move to
- Copy link
- Add label
- Delete
- Inbox
- Archive
- Drafts
- Starred
- Trash