Hover Card

ui-hover-card shows a floating card next to its trigger after the pointer has rested on it for a moment, or when the trigger receives keyboard focus. Put the link in ui-hover-card-trigger and the card in ui-hover-card-content. The card stays open while the pointer is over it, so users can move into it and click links. It is a popover="manual" element anchored to the trigger, so it does not close other popovers and is not light dismissed.

Use it for previews that sighted mouse users can do without, such as a profile summary behind a username link. Put anything essential in the page itself.

Previewindex.html
@realmorg
R
@realmorg Native-first custom elements, written as HTML. Joined December 2021
<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Hover Card demo</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@realmorg/realm@alpha/dist/realm.css">
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@realmorg/ui@alpha/dist/theme.css">
  <script type="module" src="https://cdn.jsdelivr.net/npm/@realmorg/realm@alpha/dist/realm.js"></script>
  <style>
    .demo-stack-tight {
      display: grid;
      gap: calc(var(--spacing) * 2);
    }
    .demo-text {
      margin: 0;
      font-size: var(--text-sm);
    }
    .demo-muted {
      margin: 0;
      font-size: var(--text-sm);
      color: var(--muted-foreground);
    }
    .demo-media {
      display: flex;
      align-items: flex-start;
      gap: calc(var(--spacing) * 4);
    }
  </style>
</head>
<body>
  <import-element from="https://cdn.jsdelivr.net/npm/@realmorg/ui@alpha/components/avatar.html"></import-element>
  <import-element from="https://cdn.jsdelivr.net/npm/@realmorg/ui@alpha/components/button.html"></import-element>
  <import-element from="https://cdn.jsdelivr.net/npm/@realmorg/ui@alpha/components/hover-card.html"></import-element>

  <ui-hover-card>
    <ui-hover-card-trigger><ui-button variant="link">@realmorg</ui-button></ui-hover-card-trigger>
    <ui-hover-card-content width="80">
      <div class="demo-media">
        <ui-avatar><ui-avatar-fallback>R</ui-avatar-fallback></ui-avatar>
        <div class="demo-stack-tight">
          <strong class="demo-text">@realmorg</strong>
          <span class="demo-text">Native-first custom elements, written as HTML.</span>
          <span class="demo-muted">Joined December 2021</span>
        </div>
      </div>
    </ui-hover-card-content>
  </ui-hover-card>
</body>
</html>

Examples

Delays

open-delay on ui-hover-card is the time in milliseconds before the card opens (default 500). close-delay is the time before it closes after the pointer or focus leaves (default 300).

Previewindex.html
Instant Opens and closes without delay. Slow Waits a second before opening and before closing.
<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Hover Card demo</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@realmorg/realm@alpha/dist/realm.css">
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@realmorg/ui@alpha/dist/theme.css">
  <script type="module" src="https://cdn.jsdelivr.net/npm/@realmorg/realm@alpha/dist/realm.js"></script>
  <style>
    .demo-row {
      display: flex;
      flex-wrap: wrap;
      align-items: center;
      gap: calc(var(--spacing) * 4);
    }
  </style>
</head>
<body>
  <import-element from="https://cdn.jsdelivr.net/npm/@realmorg/ui@alpha/components/button.html"></import-element>
  <import-element from="https://cdn.jsdelivr.net/npm/@realmorg/ui@alpha/components/hover-card.html"></import-element>

  <div class="demo-row">
    <ui-hover-card open-delay="0" close-delay="0">
      <ui-hover-card-trigger><ui-button variant="link">Instant</ui-button></ui-hover-card-trigger>
      <ui-hover-card-content>Opens and closes without delay.</ui-hover-card-content>
    </ui-hover-card>
    <ui-hover-card open-delay="1000" close-delay="1000">
      <ui-hover-card-trigger><ui-button variant="link">Slow</ui-button></ui-hover-card-trigger>
      <ui-hover-card-content>Waits a second before opening and before closing.</ui-hover-card-content>
    </ui-hover-card>
  </div>
</body>
</html>

Placement and width

placement on ui-hover-card-content puts the card bottom (default), top, left or right of the trigger. It flips when there is not enough room. width sets the card width in spacing units (default 64).

Previewindex.html
Top Card above the trigger. Right Card to the right. Bottom Card below the trigger. Left Card to the left.
<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Hover Card demo</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@realmorg/realm@alpha/dist/realm.css">
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@realmorg/ui@alpha/dist/theme.css">
  <script type="module" src="https://cdn.jsdelivr.net/npm/@realmorg/realm@alpha/dist/realm.js"></script>
  <style>
    .demo-row-tight {
      display: flex;
      flex-wrap: wrap;
      align-items: center;
      gap: calc(var(--spacing) * 2);
    }
  </style>
</head>
<body>
  <import-element from="https://cdn.jsdelivr.net/npm/@realmorg/ui@alpha/components/button.html"></import-element>
  <import-element from="https://cdn.jsdelivr.net/npm/@realmorg/ui@alpha/components/hover-card.html"></import-element>

  <div class="demo-row-tight">
    <ui-hover-card open-delay="100">
      <ui-hover-card-trigger><ui-button variant="outline">Top</ui-button></ui-hover-card-trigger>
      <ui-hover-card-content placement="top">Card above the trigger.</ui-hover-card-content>
    </ui-hover-card>
    <ui-hover-card open-delay="100">
      <ui-hover-card-trigger><ui-button variant="outline">Right</ui-button></ui-hover-card-trigger>
      <ui-hover-card-content placement="right" width="48">Card to the right.</ui-hover-card-content>
    </ui-hover-card>
    <ui-hover-card open-delay="100">
      <ui-hover-card-trigger><ui-button variant="outline">Bottom</ui-button></ui-hover-card-trigger>
      <ui-hover-card-content placement="bottom">Card below the trigger.</ui-hover-card-content>
    </ui-hover-card>
    <ui-hover-card open-delay="100">
      <ui-hover-card-trigger><ui-button variant="outline">Left</ui-button></ui-hover-card-trigger>
      <ui-hover-card-content placement="left" width="48">Card to the left.</ui-hover-card-content>
    </ui-hover-card>
  </div>
</body>
</html>

API

Parts

Part Slot Renders
ui-hover-card Its parts, with no box of its own. Holds the delays.
ui-hover-card-trigger (default) An inline block around the trigger. Pointer enter and focus schedule the card to open. Pointer leave and focus out schedule it to close.
ui-hover-card-content (default) A bordered popover="manual" panel with padding, anchored to the trigger. The pointer over it keeps it open.

ui-hover-card attributes

Attribute Type Default Description
open-delay number 500 Milliseconds before the card opens. Minimum 0. Property name: openDelay.
close-delay number 300 Milliseconds before the card closes. Minimum 0. Property name: closeDelay.

ui-hover-card-content attributes

Attribute Type Default Description
placement "bottom" | "top" | "left" | "right" "bottom" Side of the trigger the card appears on.
width number 64 Card width in spacing units, where n means calc(var(--spacing) * n).

CSS parts

Element Part Description
ui-hover-card-trigger trigger The wrapper that listens for pointer and focus events.
ui-hover-card-content content The padded box inside the card.

Accessibility

Edit this page on GitHub · View as Markdown