Popover

ui-popover pairs a ui-popover-trigger with a ui-popover-content. The content is the native popover API with a card style. It sets popover="auto" on itself, so it starts hidden, opens in the top layer, closes when you click outside or press Escape, and closes other auto popovers when it opens. A click on the trigger toggles it, and it is placed next to the trigger with CSS anchor positioning, flipping when there is not enough room.

ui-popover-header, ui-popover-title and ui-popover-description lay out a heading inside the content.

Previewindex.html
Open popover Dimensions Set the dimensions for the layer. Width Height
<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Popover 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>
</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/field.html"></import-element>
  <import-element from="https://cdn.jsdelivr.net/npm/@realmorg/ui@alpha/components/input.html"></import-element>
  <import-element from="https://cdn.jsdelivr.net/npm/@realmorg/ui@alpha/components/label.html"></import-element>
  <import-element from="https://cdn.jsdelivr.net/npm/@realmorg/ui@alpha/components/popover.html"></import-element>

  <ui-popover>
    <ui-popover-trigger><ui-button variant="outline">Open popover</ui-button></ui-popover-trigger>
    <ui-popover-content width="80">
      <ui-popover-header>
        <ui-popover-title>Dimensions</ui-popover-title>
        <ui-popover-description>Set the dimensions for the layer.</ui-popover-description>
      </ui-popover-header>
      <ui-field orientation="horizontal">
        <ui-label for="popover-width">Width</ui-label>
        <ui-input id="popover-width" value="100%"></ui-input>
      </ui-field>
      <ui-field orientation="horizontal">
        <ui-label for="popover-height">Height</ui-label>
        <ui-input id="popover-height" value="25px"></ui-input>
      </ui-field>
    </ui-popover-content>
  </ui-popover>
</body>
</html>

Examples

Placement

placement on ui-popover-content puts it bottom (default), top, left or right of the trigger.

Previewindex.html
Top Placed above the button. Right Placed to the right. Bottom Placed below the button. Left Placed to the left.
<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Popover 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/popover.html"></import-element>

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

Open with popovertarget or a command

ui-popover-content is a native popover, so a button anywhere on the page can open it by id with popovertarget, or commandfor with command="toggle-popover", "show-popover" or "hide-popover". The popover is then anchored to that button. A close button inside the popover can use hide-popover.

Previewindex.html
Pinned note Opened with popovertarget. Notifications You are all caught up. Dismiss
<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Popover 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);
    }
    .demo-text {
      margin: 0;
      font-size: var(--text-sm);
    }
  </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/popover.html"></import-element>

  <div class="demo-row-tight">
    <ui-button variant="outline" popovertarget="popover-target">Pinned note</ui-button>
    <ui-popover-content id="popover-target">Opened with popovertarget.</ui-popover-content>
    <ui-button variant="outline" commandfor="popover-command" command="toggle-popover">Notifications</ui-button>
    <ui-popover-content id="popover-command">
      <span class="demo-text">You are all caught up.</span>
      <ui-button size="sm" variant="secondary" commandfor="popover-command" command="hide-popover">Dismiss</ui-button>
    </ui-popover-content>
  </div>
</body>
</html>

Open from script

Call the native showPopover(), hidePopover() or togglePopover() on ui-popover-content. Pass { source } so it is anchored to the element that opened it. The native toggle event reports the new state.

Previewindex.htmlpopover-script-demo.html
Show details Popover is Opened with showPopover(). Press Escape to close.
<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Popover 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>
</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/popover.html"></import-element>

  <import-element from="./popover-script-demo.html"></import-element>
  <popover-script-demo></popover-script-demo>
</body>
</html>
<custom-element name="popover-script-demo">
  <script>
    const info = useState({ state: "closed" });

    function show() {
      refs.popover.showPopover({ source: refs.trigger });
    }

    function toggled(event) {
      info.state = event.newState;
    }
  </script>

  <style>
    :host {
      display: flex;
      align-items: center;
      gap: calc(var(--spacing) * 4);
      font-size: var(--text-sm);
    }
  </style>

  <ui-button ref="trigger" variant="outline" onclick="show()">Show details</ui-button>
  <span>Popover is <slot name="#info.state"></slot></span>
  <ui-popover-content ref="popover" ontoggle="toggled(event)">Opened with showPopover(). Press Escape to close.</ui-popover-content>
</custom-element>

Manual popovers

Set popover="manual" on the content yourself to turn off light dismiss. A manual popover stays open until it is toggled again or hidden from script.

Previewindex.html
Toggle pinned note This note stays open when you click elsewhere. Click the button again to hide it.
<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Popover 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>
</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/popover.html"></import-element>

  <ui-popover>
    <ui-popover-trigger><ui-button variant="outline">Toggle pinned note</ui-button></ui-popover-trigger>
    <ui-popover-content popover="manual">This note stays open when you click elsewhere. Click the button again to hide it.</ui-popover-content>
  </ui-popover>
</body>
</html>

API

Parts

Part Slot Renders
ui-popover Its parts, with no box of its own.
ui-popover-trigger (default) An inline block around the trigger. A click on it focuses the element inside and toggles the content, anchored to the trigger.
ui-popover-content (default) A bordered card with padding, a gap between children and popover="auto".
ui-popover-header (default) A column for the title and description, with a small gap.
ui-popover-title (default) An <h3> in var(--text-sm) medium.
ui-popover-description (default) A <p> in muted var(--text-sm).

ui-popover-content attributes

Attribute Type Default Description
placement "bottom" | "top" | "left" | "right" "bottom" Side of the anchor the popover appears on. It flips when there is not enough room.
width number 72 Width in spacing units, where n means calc(var(--spacing) * n).
popover "auto" | "manual" "auto" The native popover attribute. Set on connect when missing.

Properties and methods

ui-popover-content has the native popover methods: showPopover(options?), hidePopover() and togglePopover(options?). Use :popover-open to check whether it is open.

Events

Event Element Detail Description
beforetoggle ui-popover-content ToggleEvent Native. Fired before the popover opens or closes. Cancelable when opening.
toggle ui-popover-content ToggleEvent Native. Fired after it opens or closes. event.newState is "open" or "closed".

CSS parts

Element Part Description
ui-popover-trigger trigger The wrapper that listens for clicks.
ui-popover-title title The <h3>.
ui-popover-description description The <p>.

CSS states

Name Description
ui-popover-content:popover-open Native pseudo-class that matches while the popover is shown.

Accessibility

Edit this page on GitHub · View as Markdown