팝오버

Popover

버튼을 누르면 그 옆에 나타나는, 링크나 버튼 같은 조작 가능한 콘텐츠를 담은 작은 패널.

다른 이름: 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);

트리거 버튼에 aria-haspopup="dialog"와 aria-expanded를 달고, 팝오버 자체에 role="dialog"(또는 단순 메뉴라면 role="menu")를 씁니다. 트리거 근처에 위치를 잡되 화면 밖으로 나가면 반대쪽으로 뒤집는 "충돌 회피"가 필요합니다. 최근 브라우저는 HTML popover 속성으로 최상위 레이어링과 라이트 dismiss(바깥 클릭 시 닫힘)를 공짜로 줍니다.

툴팁과 다른 점은 위에서 설명한 대로 상호작용 가능 여부와 트리거 방식(hover vs click)입니다. 드롭다운 메뉴와는 목적이 다릅니다 — 드롭다운 메뉴는 "명령 목록 중 하나를 고른다"는 좁은 용도이고, 팝오버는 폼이나 설명, 미니 위젯처럼 더 자유로운 콘텐츠를 담는 범용 그릇입니다.

Esc와 바깥 클릭으로 닫히고, 닫히면 포커스가 트리거로 돌아와야 합니다.