Popover
트리거에 연결된 짧은 정보나 가벼운 조작을 보여줍니다.
목적
Popover는 현재 control이나 대상에 연결된 짧은 정보와 가벼운 상호작용을 그 자리에서 보여준다. 배경 맥락을 가리지 않고 필요한 순간에만 세부 내용을 드러내며 trigger와 content의 관계를 유지한다.
선택 기준
- 날짜 선택, 간단한 filter, 짧은 세부 정보처럼 trigger 가까이에서 완료되는 작업에 사용한다.
- 한 줄 설명만 필요하면 Tooltip을 사용한다.
- 여러 행동 목록은 DropdownMenu를 사용한다.
- 집중이 필요한 form이나 중요한 결정은 Dialog 또는 AlertDialog를 사용한다.
구조
Popover 아래에 PopoverTrigger와 PopoverContent를 둔다. 별도 기준점이 필요할 때 PopoverAnchor를 사용할 수 있다. Content는 theme 경계 안의 portal을 자동으로 사용한다.
Content 내부의 제목, 설명, control은 용도에 맞는 semantic element로 직접 구성한다. Popover는 Dialog처럼 Title과 Description을 자동 연결하지 않는다.
변형과 크기
PopoverContent의 기본 너비는 18rem, padding은 16px이다. align 기본값은 center, sideOffset 기본값은 4px이다. 기반 content가 지원하는 side, alignOffset, 충돌 처리 props도 전달할 수 있다.
상태와 동작
Popover는 open, defaultOpen, onOpenChange로 제어·비제어 상태를 지원한다. Content는 열린 방향에 맞춰 짧은 등장 motion을 사용한다. trigger를 다시 선택하거나 바깥 상호작용, Escape 흐름으로 닫을 수 있다.
비동기 상태가 있으면 이전 입력과 선택을 불필요하게 지우지 말고 loading, error, retry를 content 안에서 분명히 보여준다.
콘텐츠
Trigger만 보아도 무엇이 열리는지 알 수 있어야 한다. Content는 trigger가 제공하지 못한 판단 정보와 다음 행동만 담는다. 이미 화면에 있는 내용을 그대로 반복하거나 브랜드 장식을 넣어 시선을 빼앗지 않는다.
접근성
Trigger는 button 또는 적절한 interactive element여야 한다. icon-only trigger에는 접근 가능한 이름을 제공한다. keyboard focus가 content 안의 control로 자연스럽게 이동하고 닫은 뒤 trigger 맥락으로 돌아오는지 확인한다. Tooltip처럼 hover 전용으로 열지 않는다.
좁은 화면과 긴 콘텐츠
18rem 너비가 좁은 viewport를 넘지 않도록 제품 layout에서 확인한다. 긴 목록이나 여러 field가 필요하면 Sheet로 전환한다. Content에 내부 scroll을 과도하게 만들지 않고 중요한 action은 touch 환경에서도 직접 보이게 둔다.
공개 API
Popover: rootPopoverTrigger: 열기 controlPopoverAnchor: 위치 기준점PopoverContent:align="center",sideOffset={4}가 기본인 content
Content는 portal을 내부에서 사용하며 PopoverPortal은 public export가 아니다.
예제
import { Button, Input, Label } from '@classum/dot-design-system/ui';
import { Popover, PopoverContent, PopoverTrigger } from '@classum/dot-design-system/ui';
export function DueDatePopover() {
return (
<Popover>
<PopoverTrigger asChild>
<Button variant="outline">마감일 설정</Button>
</PopoverTrigger>
<PopoverContent align="end">
<div className="grid gap-2">
<Label htmlFor="due-date">마감일</Label>
<Input id="due-date" type="date" />
<p className="text-sm text-muted-foreground">학습자에게 표시되는 완료 기한이에요.</p>
</div>
</PopoverContent>
</Popover>
);
}피해야 할 사용
- 중요한 작업을 hover로만 열리는 Popover에 숨기지 않는다.
- 긴 form이나 여러 단계 흐름을 작은 Content에 넣지 않는다.
- Popover 안에 Dialog나 다른 Popover를 연속 중첩하지 않는다.
- Trigger와 무관한 전역 정보를 표시하지 않는다.
- 일반 primitive 표면에 gradient나 캐릭터를 장식으로 추가하지 않는다.