A warm window pattern stops tooltip delays from stacking

On FrontPrep, a product that lists interview questions alongside the companies that ask them, hovering over a company logo shows a tooltip with the company name. The author first set the tooltip delay to 0ms, which meant that simply sweeping the cursor across a row of logos made every tooltip in its path flash open instantly. Adding a 200ms transition delay fixed that, but created a second problem: on rows where several company logos sit side by side, moving from one logo straight to the next still meant waiting the full 200ms again for every single logo, which felt sluggish.
The fix is a three-part timing scheme built around a warm and cold state for the whole tooltip system. When the page is cold, hovering a trigger starts a 200ms open delay before the tooltip appears, so a cursor merely passing over an element on its way somewhere else never opens a tooltip. Once a tooltip closes, a 300ms warm window timer starts; hovering a different trigger inside that window opens its tooltip instantly, with no delay and no entrance animation, because the code sets a data attribute the CSS uses to skip the transition. If the 300ms window runs out without another hover, the page goes cold again and the next tooltip has to wait the full 200ms once more. Without that cold reset, the author notes, the very first tooltip opened would permanently switch off the delay for the whole page.
The implementation is a React context provider holding a warm flag as a ref, not state, so toggling it does not re-render every tooltip on the page; only the event handlers read it. Hovering a trigger checks that ref: if warm, the tooltip shows immediately, otherwise a 200ms timer is set. When a tooltip closes, markOpened cancels any pending cooldown, which is what keeps the page warm as the cursor moves from one logo to the next; markClosed starts the 300ms cooldown that eventually turns the page cold again. Leaving a trigger before its open timer fires simply clears that timer, so a fast sweep across several logos opens none of them.
On the specific numbers, the author explains that a delay under 150ms still lets a cursor that is merely passing over a trigger open the tooltip, while a delay over 250ms makes a deliberate hover feel sluggish or broken, which is why he settled on 200ms; the close delay is set to 0ms because leaving a trigger is unambiguous and there is nothing worth waiting for. FrontPrep's own tooltips are built with Radix and Motion, though the post demonstrates the pattern with a simpler React version, and links to a separate follow-up article that reproduces the same before-and-after behaviour with no JavaScript at all.
The author frames the piece around a broader point: AI can build a fully functional tooltip, but only a human with developed taste and judgement decides whether the result is actually polished, and AI only produces a polished result when guided there. In that spirit, he packaged the pattern into a Claude skill, a SKILL.md file included in the post, that a developer can point at their own codebase to audit its tooltip implementation for the same delay problem, regardless of which tooltip library or custom tooltip code that codebase uses.
Key facts
- Setting the tooltip delay to 0ms on FrontPrep made every logo under a cursor sweep flash a tooltip instantly.
- A flat 200ms delay fixed that but made moving between adjacent logos feel sluggish, since each new hover retriggered the full wait.
- The fix uses three numbers: a 200ms open delay while the page is cold, a 300ms warm window after a tooltip closes during which the next tooltip opens instantly, and a 0ms close delay.
- The author's own testing put the open delay's usable range between 150ms (below which a passing cursor still opens the tooltip) and 250ms (above which a deliberate hover feels sluggish), landing on 200ms.
- The pattern ships with a Claude skill, a SKILL.md file, meant to let a developer audit any existing codebase for the same tooltip-timing problem, alongside the author's own Radix and Motion based implementation in FrontPrep.
Why it matters
A naive tooltip delay forces a tradeoff: either every element under a moving cursor flashes a tooltip, or every fresh hover on an adjacent element feels laggy. The warm and cold pattern threads that needle with two timers instead of one, and the author points out it is the same interaction already used in browser toolbars, so this gives a name and a concrete recipe to a pattern many developers may sense is needed but have not isolated or built themselves.
Who it affects
Front end developers building tooltips, popovers or similar hover driven UI over rows of adjacent triggers, such as logo grids, icon toolbars, or menus with several hoverable items placed close together. End users of any interface with multiple nearby hover targets feel the difference directly, whether or not they can name what changed.
How to use it
The full code is shown in the blog post: a React context provider that tracks a warm ref and a cooldown timer, plus a CSS rule that skips the transition when a data attribute marks the tooltip as instant. It sits alongside whatever tooltip component a project already uses; FrontPrep itself builds its tooltips with Radix and Motion, while the post's example uses a simpler React version. The author also published a Claude skill, a SKILL.md file, that can be pointed at an existing codebase to audit its own tooltip implementation for this same delay problem, described as working across different tooltip libraries or custom tooltip code.
How solid is it
This is one developer's account of a fix he built and shipped in his own product, not an academic or peer reviewed study. The 150ms, 200ms, 250ms and 300ms figures come from his own trial and adjustment, described in the post as a good, balanced number rather than the output of a controlled user study. The post includes the actual React and CSS code involved and links a before and after video of the effect on the author's own site, giving readers a way to see the claimed improvement rather than take it on faith.
Risks and caveats
The specific timings are one developer's judgement call for one product's interface and cursor behaviour, not universal constants, and may need retuning for a different layout or interaction pattern. The pattern also adds real implementation complexity, a shared warm state, refs and two separate timers, to something a single CSS transition-delay property would otherwise handle. The claim that the accompanying Claude skill 'will work for all' codebases and tooltip libraries is the author's own description of it, not something the post independently verifies.
“A click is always intentional whereas a hover is not intentional. The cursor travels across the page to get wherever it has to, and it passes over elements on the way, so a tooltip cannot tell from the hover whether the user wants to open it.”
— the author, in the post's Claude skill file