Paint feedback first

Paint a pending state in the next frame; do the heavy work after.

Guillermo Rauch@rauchg
“INP is often misunderstood to require painting the full user response within 200ms, when it is really about giving the user feedback that their input is being processed within that time” This article is a must read
Jun 12, 2024View on X ↗
Guillermo Rauch@rauchg
First battle was page loading speed. Next boss is interaction speed. INP, now a Core Web Vital, is tricky to optimize. We built a tool to help:
May 22, 2024View on X ↗
Guillermo Rauch@rauchg
The @vercel Toolbar INP debugging feature is 🤯 It prevents slowness from creeping in. When an interaction exceeds the acceptable threshold, a toast is shown.
Apr 7, 2024View on X ↗

Demo 2 mimics the Vercel Toolbar's slow-interaction toast.

1 · Sort 20,000 invoices

Press Sort in each pane and watch the button.

Work, then paintBad
Paint, then workGood
const nextPaint = () => new Promise((r) => requestAnimationFrame(() => setTimeout(r)));

sortButton.addEventListener("click", async () => {
  sortButton.dataset.pending = "";        // 1. the feedback
  sortButton.textContent = "Sorting…";
  await nextPaint();                      // 2. let the browser paint it
  render(sortInvoices(invoices));         // 3. the heavy work
  delete sortButton.dataset.pending;
});
// React: startTransition(() => setSort("amount")) paints isPending first.

2 · Flag slow interactions

Click the actions; any over 200ms raises a toast.

INP monitorWork first
Worst next paint–Threshold 200ms

Why it matters, pros and cons

Why it matters

INP times input to next paint. A pending state painted in one frame answers the user; the work can finish after.

Pros

  • INP drops even when the total work stays the same.
  • People see the click landed, so they don't click twice.
  • Three lines: set state, yield a frame, then work.

Cons

  • The work still blocks after the paint: split long tasks too.
  • A pending state on a 30ms task is just a flicker.
  • Yielding lets clicks interleave: guard against stale ones.