← Back
[W] Writing

The safe triangle

The safe triangle is one of those things you never notice until it's missing.

Open the menu below and try to reach Target, at the bottom of the submenu. Go straight for it, the way your hand wants to.

Try it with the triangle off, then on. On a phone, or if you'd rather watch, use the button. There's no hover on touch, so this problem doesn't exist there.

With it off, you probably lost the submenu. Your cursor crossed Share on its way across, and the menu did exactly what it was told. It switched.

Nobody moves along a neat path, right and then down. Your hand takes the shortest line, and that line runs over other items.

How it works

While you're over an item, the menu remembers where your cursor is. When you move onto a different item, it draws a triangle from that point to the top and bottom corners of the submenu.

  1. Cursor crosses a new item
  2. Inside the triangle? You're heading for the submenu
  3. Hold the current submenu for a moment
If the cursor is outside the triangle, you clearly meant the new item, so it switches straight away.

The check itself is short. Is this point inside this triangle?

const area = (a, b, c) =>
  (a.x - c.x) * (b.y - c.y) - (b.x - c.x) * (a.y - c.y);

function inside(p, a, b, c) {
  const d1 = area(p, a, b);
  const d2 = area(p, b, c);
  const d3 = area(p, c, a);
  const negative = d1 < 0 || d2 < 0 || d3 < 0;
  const positive = d1 > 0 || d2 > 0 || d3 > 0;
  return !(negative && positive);
}

It's the same code that's running in the demo above.

The part that's easy to miss

A triangle alone creates a new bug. If you stop inside it, the menu is stuck on the old submenu even though you're resting on another item.

So staying in the triangle only buys time. The demo waits 300ms. If you're still there after that, you've clearly stopped travelling, and it switches.

That number is a feel decision, and there isn't a right answer. Too short and slow movers lose the submenu. Too long and the menu feels broken.

You probably don't need to write this

This idea is old. Ben Kamens wrote it up in 2013 in a post about Amazon's mega dropdown, and libraries like Floating UI ship a version called safePolygon. Use one of those if you can.

What I'd take from it is the way of looking. Someone watched how a hand really moves, noticed the interface assumed something else, and fixed the interface. The fix is invisible, and that's why I like it so much. When it works, there's nothing to see.

Next