Skip to the solution
MediumMachine Coding12 min read

Build a Tooltip

80 views

The problem

Question presented to candidate: "Build a reusable tooltip. It should appear when you hover over a button or focus it with the keyboard, accept a preferred side (top, right, bottom or left), and never end up off screen: if there is no room on the preferred side, flip it, and if it would overflow sideways, slide it back in."

Requirements:

  • Show on hover after a short delay (300 ms), immediately on keyboard focus; hide on mouse leave after a short delay (100 ms), on blur and on Escape.
  • The pointer can move from the trigger onto the tooltip without it disappearing.
  • Placement prop: top, right, bottom, left, with an 8 px gap from the trigger.
  • Flip to the opposite side when the preferred side does not fit; shift along the other axis to stay 8 px inside the viewport.
  • Rendered in a portal with position: fixed; follows the trigger on scroll and resize.
  • role="tooltip" and aria-describedby on the trigger.

What a strong answer should cover:

  • Positioning as a pure function of the trigger rect, the tooltip size, the placement and the viewport: easy to reason about and to test.
  • Measuring after render but before paint, so the tooltip never flashes at the wrong place.
  • Why a portal and position: fixed (clipping and stacking contexts), and how scroll in any container is caught (capture phase).
  • Hover and focus parity, delays with a single timer, and WCAG 1.4.13 (dismissible with Escape, hoverable, persistent).
  • When to reach for a library such as Floating UI, and the CSS anchor positioning alternative.

Clarifying questions expected:

  • "Plain text only, or rich interactive content? (Interactive content is a popover, not a tooltip.)"
  • "Should touch devices show it, and how?"
  • "Do we need an arrow pointing at the trigger?"

Code / implementation expected: Yes. A positioning function, a reusable tooltip and a demo with each placement plus a flip and a shift case.

  • React
  • Positioning
  • UI

Try it yourself

Sketch your approach before you read the solution. That is what the interview tests.

Stuck? Get a hint.

A short nudge toward the approach. It will not give the answer away.

Solution

The solution is hidden so you can try first

12 min read ยท 9 sections

React solution

Every file of the working solution. Open it in the playground to run and change it.

ReactComplete solution
import Tooltip from "./src/components/Tooltip";

const SIDES = ["top", "right", "bottom", "left"];

export default function App() {
  return (
    <main className="page">
      <div className="edges">
        <Tooltip content="No room above, so I flip below" placement="top">
          {(props) => (
            <button {...props} className="btn" data-testid="edge-top">
              Flips
            </button>
          )}
        </Tooltip>
        <Tooltip
          content="A longer tooltip that is shifted left to stay on screen"
          placement="bottom"
        >
          {(props) => (
            <button {...props} className="btn" data-testid="edge-right">
              Shifts
            </button>
          )}
        </Tooltip>
      </div>
      <h1>Tooltip</h1>
      <p className="hint">
        Hover (300 ms delay) or Tab to a button. Escape hides the tooltip.
      </p>
      <div className="grid">
        {SIDES.map((side) => (
          <Tooltip key={side} content={"Placed " + side} placement={side}>
            {(props) => (
              <button {...props} className="btn" data-testid={"tt-" + side}>
                {side}
              </button>
            )}
          </Tooltip>
        ))}
      </div>
    </main>
  );
}

Discussion

Other approaches, follow-ups and how it went in real interviews.

Sign in to join the discussion.

No comments yet. Share how you would answer it.

Question 74 of 107 in Machine coding

Keep your momentum going.

Mark this question solved to track your progress, then take the next one while it is fresh.

Up nextMedium

Build a Kanban Board with Swimlanes & WIP Limits

Continue