DEV Community

Cover image for I deleted 250 lines of tooltip positioning logic and replaced it with one prop
Srinath-g639
Srinath-g639

Posted on

I deleted 250 lines of tooltip positioning logic and replaced it with one prop

Had a hover card component in production. floating-ui, portal, resize observers, scroll listeners. ~400 lines. Standard tooltip positioning stack.

During a refactor I actually read through it and realized the browser already knows how to solve this.

Replaced the whole thing with layoutId from motion/react. Trigger avatar and card avatar share the same ID. Card opens, trigger unmounts, card mounts. Motion interpolates between the two positions automatically. Spring physics. No coordinate math. No portal.

{!open && (
  <motion.div layoutId={`${uid}-av`} className="size-10 rounded-full overflow-hidden">
    <Avatar />
  </motion.div>
)}

// inside the expanded card
<motion.div layoutId={`${uid}-av`} className="size-10 rounded-full overflow-hidden">
  <Avatar />
</motion.div>
Enter fullscreen mode Exit fullscreen mode

Things that bit me:

Hover intent timers are non-negotiable. 80ms show, 100ms hide. Without this, moving across a row of avatars is a strobe light.

One layoutId = one DOM element. If both exist simultaneously the animation silently breaks. No error. Just a hard cut. Cost me an embarrassing amount of time.

Stagger your content reveals. ~60ms between each section. Individually invisible. Together it makes the card feel intentional instead of cheap.

Where it falls short: no viewport edge detection. If you need tooltip flipping, you still need floating-ui.

Result was ~160 lines. The diff deleted more code than it added.

Wrote a longer breakdown with a live demo here if anyone wants the full implementation.

Top comments (0)