Popover

팝오버

A small panel of interactive content — buttons, links — that opens next to the button that triggered it.

Also known as: FlyoutPopup panelAnchored panel
···
html
<div class="wrap">
  <button class="trigger" id="tb" aria-haspopup="dialog" aria-expanded="false">공유</button>
  <div class="pop" id="pp" role="dialog" aria-label="공유 옵션">
    <div class="link-row"><input readonly value="atlas.design/x1"><button class="mini">복사</button></div>
    <div class="icons"><button class="icon-btn2">✉️</button><button class="icon-btn2">🔗</button></div>
  </div>
</div>
css
.wrap{position:relative;display:grid;place-items:center;width:100%;height:100%}
.trigger{padding:8px 18px;border-radius:9px;border:1px solid var(--line);background:var(--surface);color:var(--fg);font-size:13px;font-weight:600;cursor:pointer}
.pop{position:absolute;left:50%;bottom:calc(50% + 30px);transform:translate(-50%,6px) scale(.96);width:190px;
  background:var(--surface);border:1px solid var(--line);border-radius:12px;padding:10px;display:grid;gap:8px;
  box-shadow:0 16px 34px rgba(0,0,0,.22);opacity:0;pointer-events:none;transition:opacity .18s,transform .18s}
.pop[data-open]{opacity:1;pointer-events:auto;transform:translate(-50%,0) scale(1)}
.link-row{display:flex;gap:6px}
.link-row input{flex:1;min-width:0;font-size:11px;border:1px solid var(--line);border-radius:6px;padding:5px 7px;background:var(--bg);color:var(--muted)}
.mini{border:0;background:var(--accent);color:#fff;border-radius:6px;padding:0 9px;font-size:11px;font-weight:700;cursor:pointer}
.icons{display:flex;gap:6px}
.icon-btn2{flex:1;border:1px solid var(--line);background:var(--bg);border-radius:6px;padding:5px 0;font-size:13px;cursor:pointer}
js
const tb = document.getElementById('tb'), pp = document.getElementById('pp');
function open(v) { pp.toggleAttribute('data-open', v); tb.setAttribute('aria-expanded', String(v)); }
let auto = true;
tb.addEventListener('click', () => { auto = false; open(pp.getAttribute('data-open') === null); });
document.addEventListener('click', (e) => { if (!pp.contains(e.target) && e.target !== tb) open(false); });
function loop() { if (!auto) return; open(true); setTimeout(() => { if (auto) { open(false); setTimeout(loop, 900); } }, 2100); }
setTimeout(loop, 500);

Give the trigger aria-haspopup="dialog" and aria-expanded, and the popover itself role="dialog" (or role="menu" if it's really just a command list). Position it near the trigger with collision avoidance — flip to the other side if it would run off-screen. The native HTML popover attribute now gives top-layer stacking and light-dismiss (closing on outside click) for free.

It differs from a tooltip in interactivity and trigger, as described there. It differs from a dropdown menu in purpose — a dropdown menu narrowly picks one item from a command list, while a popover is a general-purpose container for freer content like a form, an explanation, or a mini widget.

It closes on Esc and outside click, and focus should return to the trigger when it closes.