Component Library

← Back to gallery

Popover

Category: Overlays · Tags: popover, disclosure, info, anchored, toggle

Your plan renews on 1 April.

How to use it

Use for a short explanation the user may want next to a term or setting, such as what a plan includes. Do not put essential information, form fields or long content in it (show that inline or use a dialog), and do not use it for a one-line hint on hover (use a tooltip). After copying, give the panel a unique id and update the button's aria-controls to match.

Accessibility

A native <button> toggles the panel and reports its state with aria-expanded and aria-controls, so screen readers announce it as an expandable control; the panel is not modal and stays in the normal reading and Tab order right after the button. Escape closes it and returns focus to the button, and a click anywhere outside closes it. The button text is #1e40af on #ffffff (8.72:1), panel text is #0f172a on #ffffff (17.85:1) and its heading #334155 on #ffffff (10.35:1).

Source (copy-ready)

<div class="dcl-popover">
  <p class="dcl-popover__text">Your plan renews on 1 April.
    <span class="dcl-popover__anchor">
      <button type="button" class="dcl-popover__toggle" aria-expanded="false" aria-controls="dcl-popover-panel">What is included?</button>
      <span class="dcl-popover__panel" id="dcl-popover-panel" hidden>
        <strong class="dcl-popover__heading">Team plan</strong>
        <span class="dcl-popover__body">Ten seats, 100 GB of shared storage and email support with a one-day reply time.</span>
      </span>
    </span>
  </p>
</div>
<style>
.dcl-popover { position: relative; font: inherit; color: #0f172a; background-color: #ffffff; max-width: 100%; }
.dcl-popover__text { margin: 0; line-height: 1.6; color: #0f172a; background-color: #ffffff; }
.dcl-popover__anchor { display: inline-block; }
.dcl-popover__toggle { font: inherit; padding: 0.15rem 0.4rem; border: 1px solid #1e40af; border-radius: 4px; cursor: pointer; color: #1e40af; background-color: #ffffff; }
.dcl-popover__toggle:hover { color: #ffffff; background-color: #1e40af; }
.dcl-popover__toggle:focus-visible { outline: 2px solid #0f172a; outline-offset: 2px; }
.dcl-popover__panel { position: absolute; top: calc(100% + 0.4rem); left: 0; z-index: 20; display: block; width: 16rem; max-width: 100%; box-sizing: border-box; padding: 0.75rem 0.9rem; border: 1px solid #94a3b8; border-radius: 8px; box-shadow: 0 6px 18px #cbd5e1; color: #0f172a; background-color: #ffffff; }
.dcl-popover__panel[hidden] { display: none; }
.dcl-popover__heading { display: block; margin-bottom: 0.25rem; color: #334155; background-color: #ffffff; }
.dcl-popover__body { display: block; line-height: 1.45; color: #0f172a; background-color: #ffffff; }
</style>
<script>
(function () {
  document.querySelectorAll(".dcl-popover").forEach(function (root) {
    if (root.dataset.dclBound) { return; }
    root.dataset.dclBound = "true";
    var toggle = root.querySelector(".dcl-popover__toggle");
    var panel = root.querySelector(".dcl-popover__panel");
    if (!toggle || !panel) { return; }
    function setOpen(open) {
      panel.hidden = !open;
      toggle.setAttribute("aria-expanded", open ? "true" : "false");
    }
    toggle.addEventListener("click", function () { setOpen(panel.hidden); });
    root.addEventListener("keydown", function (event) {
      if (event.key === "Escape" && !panel.hidden) {
        setOpen(false);
        toggle.focus();
      }
    });
    document.addEventListener("click", function (event) {
      if (!panel.hidden && !root.contains(event.target)) { setOpen(false); }
    });
  });
})();
</script>

Was this useful? Send feedback.