본문으로 건너뛰기
오버레이 / popover

Popover

트리거에 앵커되어 뜨는 인터랙티브 부동 패널 (Radix Popover 기반).
오버레이popoverStatic specimenpopover팝오버부동패널floating
01 · Specimen

먼저 보고, 그다음 계약을 읽습니다

트리거에 앵커되어 뜨는 인터랙티브 부동 패널 (Radix Popover 기반).

Workbench 불러오는 중…
Component intent의도와 경계 읽기

Tooltip 보다 무겁고 Dialog 보다 가벼운 중간 오버레이다. 폼·미니 메뉴·인스펙터처럼 상호작용이 있는 콘텐츠를 트리거 옆에 띄운다. Dialog 와 달리 포커스를 가두지 않고(modal 기본 false) 바깥 상호작용을 허용하며, Esc 로 닫는다. 기본으로 포털에 렌더되어 overflow:hidden 부모에 갇히지 않고, side/align/sideOffset 등 배치는 Radix Popover 가 popper 로 계산한다. Popover(Root)·PopoverTrigger·PopoverContent 를 조합하고, 필요 시 PopoverArrow·PopoverClose·PopoverAnchor 를 더한다.

02 · Use

예제

SSOT에 등록된 실제 API 기준 snippet입니다. standalone 배지만 독립 실행 단위이며, fragment는 주변 state·handler 문맥을 생략합니다.

01기본 (인스펙터 패널)tsxfragment
기본 (인스펙터 패널)
import {  Popover,  PopoverTrigger,  PopoverContent,  PopoverArrow,  Button,} from "@axe/ui";<Popover>  <PopoverTrigger asChild>    <Button variant="ghost">필터</Button>  </PopoverTrigger>  <PopoverContent side="bottom" align="end">    <PopoverArrow />    {/* … 필터 폼 … */}  </PopoverContent></Popover>
02controlled + PopoverClosetsxfragment
controlled + PopoverClose
import {  Popover,  PopoverTrigger,  PopoverContent,  PopoverClose,  Button,} from "@axe/ui";<Popover open={open} onOpenChange={setOpen}>  <PopoverTrigger asChild>    <Button>공유</Button>  </PopoverTrigger>  <PopoverContent sideOffset={12}>    <p>이 문서 링크를 복사합니다.</p>    <PopoverClose asChild>      <Button variant="ghost">닫기</Button>    </PopoverClose>  </PopoverContent></Popover>
03 · React

Props

TSX 소스가 진실입니다. 주요 export 컴포넌트의 public API만 노출합니다.

이름타입필수기본값설명
openboolean열림 상태 (controlled). Radix Popover.Root prop.
onOpenChange(open: boolean) => void열림/닫힘 전환 콜백 (Root).
defaultOpenbooleanfalseuncontrolled 초기 열림 상태 (Root).
modalbooleanfalsetrue 면 바깥 상호작용 차단·포커스 트랩. 기본은 비모달 (Root).
side"top" | "right" | "bottom" | "left""bottom"트리거 기준 배치 방향 (PopoverContent, Radix Content prop).
align"start" | "center" | "end""center"교차축 정렬 (PopoverContent, Radix).
sideOffsetnumber8PopoverContent 와 트리거 사이 간격(px).
withPortalbooleantruePopoverContent 를 포털로 띄울지. false 면 DOM 위치 그대로(트리거 옆)에 렌더.
...rest (PopoverContent)React.ComponentPropsWithoutRef<typeof Popover.Content>collisionPadding·onOpenAutoFocus·onEscapeKeyDown 등 Radix Content props 를 전파.
...rest (PopoverArrow)React.ComponentPropsWithoutRef<typeof Popover.Arrow>화살표 표식. 기본 width 12·height 6 로 렌더(Radix Arrow props 전파).
04 · Any stack

.axe-* 클래스 계약

React 밖에서도 같은 표면을 그리는 공개 계약입니다. stable은 minor 버전 안에서 이름을 바꾸지 않습니다.

클래스안정성용도
.axe-popover__contentstable부동 패널 표면(elevated 배경·shadow-lg·min-width 200).
.axe-popover__arrowstable트리거를 가리키는 삼각 화살표(fill=elevated·drop-shadow 보더).
비-React 소비 노트
표면 스타일(.axe-popover__content/.axe-popover__arrow)은 노출되지만, 트리거 기준 위치 계산(side/align/sideOffset)·포털·open/close(data-state)는 전적으로 Radix popper 런타임에 의존한다. 따라서 CSS-only 로는 앵커된 팝오버를 재현할 수 없고 실제 소비는 React 컴포넌트를 통해서 한다.
05 · Inclusive

접근성

키보드, ARIA, 구현 노트를 함께 검토합니다.

Keyboard
  • Space/Enter 로 열기(트리거)
  • 열릴 때 포커스가 콘텐츠 첫 요소로 이동
  • Esc 로 닫기(트리거로 포커스 복원)
  • Tab 으로 콘텐츠 내부를 이동(비모달이라 가두지 않음)
ARIA

Radix 가 트리거에 aria-haspopup=dialog·aria-expanded·aria-controls 를 부여하고 콘텐츠와 id 로 연결한다. 콘텐츠 자체는 인터랙티브 컨테이너이므로, 의미가 필요하면 소비자가 aria-label/role 을 명시한다.

Notes

Dialog 와 달리 포커스 트랩이 없다(modal 기본 false) — 여러 트리거/폼 필드와 나란히 열어두는 데 적합. transform-origin 을 Radix 의 --radix-popover-content-transform-origin 에 맞춰 방향별 확대 애니메이션을 주고, data-state=open|closed 로 진입/퇴장이 갈린다. focus-visible 시 accent outline, prefers-reduced-motion 시 애니메이션 제거.

06 · Judgment

권장 · 지양

권장
  • 인터랙티브 콘텐츠(폼·미니 메뉴·설정)에 쓸 것.
  • 단순 텍스트 힌트는 Tooltip, 확인·집중이 필요한 흐름은 Dialog 로 분리.
  • 포털 밖 위치가 필요하면 withPortal={false}, 앵커를 분리하려면 PopoverAnchor 사용.
지양
  • 다량의 텍스트나 전체 워크플로를 넣지 말 것 — 그건 Dialog/Sheet.
  • 포커스 격리가 필요한 파괴적 확인에 비모달 Popover 를 쓰지 말 것 — modal 다이얼로그로.
검색창을 열면 컴포넌트 인덱스를 불러옵니다.