Popover
먼저 보고, 그다음 계약을 읽습니다
트리거에 앵커되어 뜨는 인터랙티브 부동 패널 (Radix Popover 기반).
Component intent의도와 경계 읽기
Tooltip 보다 무겁고 Dialog 보다 가벼운 중간 오버레이다. 폼·미니 메뉴·인스펙터처럼 상호작용이 있는 콘텐츠를 트리거 옆에 띄운다. Dialog 와 달리 포커스를 가두지 않고(modal 기본 false) 바깥 상호작용을 허용하며, Esc 로 닫는다. 기본으로 포털에 렌더되어 overflow:hidden 부모에 갇히지 않고, side/align/sideOffset 등 배치는 Radix Popover 가 popper 로 계산한다. Popover(Root)·PopoverTrigger·PopoverContent 를 조합하고, 필요 시 PopoverArrow·PopoverClose·PopoverAnchor 를 더한다.
예제
SSOT에 등록된 실제 API 기준 snippet입니다. standalone 배지만 독립 실행 단위이며, fragment는 주변 state·handler 문맥을 생략합니다.
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>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>Props
TSX 소스가 진실입니다. 주요 export 컴포넌트의 public API만 노출합니다.
| 이름 | 타입 | 필수 | 기본값 | 설명 |
|---|---|---|---|---|
open | boolean | — | — | 열림 상태 (controlled). Radix Popover.Root prop. |
onOpenChange | (open: boolean) => void | — | — | 열림/닫힘 전환 콜백 (Root). |
defaultOpen | boolean | — | false | uncontrolled 초기 열림 상태 (Root). |
modal | boolean | — | false | true 면 바깥 상호작용 차단·포커스 트랩. 기본은 비모달 (Root). |
side | "top" | "right" | "bottom" | "left" | — | "bottom" | 트리거 기준 배치 방향 (PopoverContent, Radix Content prop). |
align | "start" | "center" | "end" | — | "center" | 교차축 정렬 (PopoverContent, Radix). |
sideOffset | number | — | 8 | PopoverContent 와 트리거 사이 간격(px). |
withPortal | boolean | — | true | PopoverContent 를 포털로 띄울지. 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 전파). |
.axe-* 클래스 계약
React 밖에서도 같은 표면을 그리는 공개 계약입니다. stable은 minor 버전 안에서 이름을 바꾸지 않습니다.
| 클래스 | 안정성 | 용도 |
|---|---|---|
.axe-popover__content | stable | 부동 패널 표면(elevated 배경·shadow-lg·min-width 200). |
.axe-popover__arrow | stable | 트리거를 가리키는 삼각 화살표(fill=elevated·drop-shadow 보더). |
접근성
키보드, ARIA, 구현 노트를 함께 검토합니다.
- Space/Enter 로 열기(트리거)
- 열릴 때 포커스가 콘텐츠 첫 요소로 이동
- Esc 로 닫기(트리거로 포커스 복원)
- Tab 으로 콘텐츠 내부를 이동(비모달이라 가두지 않음)
Radix 가 트리거에 aria-haspopup=dialog·aria-expanded·aria-controls 를 부여하고 콘텐츠와 id 로 연결한다. 콘텐츠 자체는 인터랙티브 컨테이너이므로, 의미가 필요하면 소비자가 aria-label/role 을 명시한다.
Dialog 와 달리 포커스 트랩이 없다(modal 기본 false) — 여러 트리거/폼 필드와 나란히 열어두는 데 적합. transform-origin 을 Radix 의 --radix-popover-content-transform-origin 에 맞춰 방향별 확대 애니메이션을 주고, data-state=open|closed 로 진입/퇴장이 갈린다. focus-visible 시 accent outline, prefers-reduced-motion 시 애니메이션 제거.