GitHub

Components / Overlays & Dialogs / Hover Card

Hover Card beta

A richer tooltip for things with a face: profiles, previews, and anything a title attribute cannot carry.

Preview

The release notes were drafted by Aoi Kimura AK

Aoi Kimura

Product designer, Tokyo

Owns the design system and the Motion line. Usually replies within the hour.

and are ready for review.

Uses: Avatar — include its CSS alongside this one.

<p style="font-size:13.5px;color:var(--k-ink-2)">The release notes were drafted by
  <span class="k-hover" data-hover>
    <a class="trigger" href="#">Aoi Kimura</a>
    <span class="card">
      <span style="display:flex;gap:11px;align-items:center"><span class="k-avatar" data-size="lg">AK</span><span><h4>Aoi Kimura</h4><p style="margin:0">Product designer, Tokyo</p></span></span>
      <p>Owns the design system and the Motion line. Usually replies within the hour.</p>
    </span>
  </span>
  and are ready for review.</p>
.k-hover{position:relative;display:inline-block;font-family:var(--k-font)}
.k-hover .card{position:absolute;left:50%;top:calc(100% + 10px);transform:translate(-50%,4px);width:262px;background:var(--k-bg);border:1px solid var(--k-line);border-radius:14px;box-shadow:0 16px 40px -12px rgba(16,24,40,.18);padding:15px;text-align:left;opacity:0;pointer-events:none;transition:opacity .16s var(--k-ease),transform .16s var(--k-ease);z-index:40}
.k-hover.open .card{opacity:1;pointer-events:auto;transform:translate(-50%,0)}
.k-hover .card h4{font-size:13.5px;font-weight:600;color:var(--k-ink)}
.k-hover .card p{margin-top:4px;font-size:12.5px;line-height:1.65;color:var(--k-ink-2)}
.k-hover .trigger{font-weight:550;color:var(--k-accent);cursor:pointer;text-decoration:underline;text-underline-offset:3px;text-decoration-color:var(--k-accent-line)}
document.querySelectorAll('[data-hover]').forEach(wrap => {
  let openT, closeT;
  const open = () => { clearTimeout(closeT); openT = setTimeout(() => wrap.classList.add('open'), 300); };
  const close = () => { clearTimeout(openT); closeT = setTimeout(() => wrap.classList.remove('open'), 180); };
  wrap.addEventListener('pointerenter', open);
  wrap.addEventListener('pointerleave', close);
  wrap.addEventListener('focusin', () => { clearTimeout(closeT); wrap.classList.add('open'); });
  wrap.addEventListener('focusout', close);
});

Usage

For profile previews on names and avatars. Rich content only — anything actionable belongs in a Popover, which also works on tap.

Accessibility

Opens on focus as well as hover, with a delay both ways so it never flickers. Touch users get the Popover pattern instead; never hide essential content here.

Related parts