Popover

Popover는 트리거 요소 근처에 부가 정보나 상호작용 콘텐츠를 표시하는 오버레이 컴포넌트입니다. 툴팁, 메뉴, 폼, 상세 정보 등을 표시할 때 사용합니다.
'use client';

import { Button, Popover } from '@vapor-ui/core';

export default function DefaultPopover() {
    return (
        <div className="flex justify-center p-20">
            <Popover.Root>
                <Popover.Trigger render={<Button variant="outline" />}>팝오버 열기</Popover.Trigger>
                <Popover.Popup>
                    <Popover.Title>알림</Popover.Title>
                    <Popover.Description>
                        새로운 메시지 3개와 알림 1개가 있습니다.
                    </Popover.Description>
                </Popover.Popup>
            </Popover.Root>
        </div>
    );
}

Property


PositionerProps

Popover가 나타날 위치와 정렬을 설정할 수 있습니다. 기본값은 'bottom'입니다.

'use client';

import { Button, Popover } from '@vapor-ui/core';

export default function PopoverPositioning() {
    return (
        <div className="grid grid-cols-2 gap-8 p-20">
            <div className="space-y-6">
                <h3 className="text-sm font-medium text-foreground-hint">방향 설정</h3>
                <div className="grid grid-cols-2 gap-4">
                    <Popover.Root>
                        <Popover.Trigger render={<Button variant="outline" />}>
                            상단 팝오버
                        </Popover.Trigger>
                        <Popover.Popup
                            positionerElement={<Popover.PositionerPrimitive side="top" />}
                        >
                            <Popover.Title>상단 팝오버</Popover.Title>
                            <Popover.Description>
                                트리거 위쪽에 표시되는 팝오버입니다.
                            </Popover.Description>
                        </Popover.Popup>
                    </Popover.Root>

                    <Popover.Root>
                        <Popover.Trigger render={<Button variant="outline" />}>
                            우측 팝오버
                        </Popover.Trigger>
                        <Popover.Popup
                            positionerElement={<Popover.PositionerPrimitive side="right" />}
                        >
                            <Popover.Title>우측 팝오버</Popover.Title>
                            <Popover.Description>
                                트리거 오른쪽에 표시되는 팝오버입니다.
                            </Popover.Description>
                        </Popover.Popup>
                    </Popover.Root>

                    <Popover.Root>
                        <Popover.Trigger render={<Button variant="outline" />}>
                            하단 팝오버
                        </Popover.Trigger>
                        <Popover.Popup
                            positionerElement={<Popover.PositionerPrimitive side="bottom" />}
                        >
                            <Popover.Title>하단 팝오버</Popover.Title>
                            <Popover.Description>
                                트리거 아래쪽에 표시되는 팝오버입니다.
                            </Popover.Description>
                        </Popover.Popup>
                    </Popover.Root>

                    <Popover.Root>
                        <Popover.Trigger render={<Button variant="outline" />}>
                            좌측 팝오버
                        </Popover.Trigger>
                        <Popover.Popup
                            positionerElement={<Popover.PositionerPrimitive side="left" />}
                        >
                            <Popover.Title>좌측 팝오버</Popover.Title>
                            <Popover.Description>
                                트리거 왼쪽에 표시되는 팝오버입니다.
                            </Popover.Description>
                        </Popover.Popup>
                    </Popover.Root>
                </div>
            </div>

            <div className="space-y-6">
                <h3 className="text-sm font-medium text-foreground-hint">정렬 설정</h3>
                <div className="space-y-4">
                    <Popover.Root>
                        <Popover.Trigger render={<Button variant="outline" />}>
                            시작점 정렬
                        </Popover.Trigger>
                        <Popover.Popup
                            positionerElement={<Popover.PositionerPrimitive align="start" />}
                        >
                            <Popover.Title>시작점 정렬</Popover.Title>
                            <Popover.Description>
                                트리거의 시작점에 정렬된 팝오버입니다.
                            </Popover.Description>
                        </Popover.Popup>
                    </Popover.Root>

                    <Popover.Root>
                        <Popover.Trigger render={<Button variant="outline" />}>
                            중앙 정렬
                        </Popover.Trigger>
                        <Popover.Popup
                            positionerElement={<Popover.PositionerPrimitive align="center" />}
                        >
                            <Popover.Title>중앙 정렬</Popover.Title>
                            <Popover.Description>
                                트리거의 중앙에 정렬된 팝오버입니다.
                            </Popover.Description>
                        </Popover.Popup>
                    </Popover.Root>

                    <Popover.Root>
                        <Popover.Trigger render={<Button variant="outline" />}>
                            끝점 정렬
                        </Popover.Trigger>
                        <Popover.Popup
                            positionerElement={<Popover.PositionerPrimitive align="end" />}
                        >
                            <Popover.Title>끝점 정렬</Popover.Title>
                            <Popover.Description>
                                트리거의 끝점에 정렬된 팝오버입니다.
                            </Popover.Description>
                        </Popover.Popup>
                    </Popover.Root>
                </div>
            </div>
        </div>
    );
}

Offset

Popover와 트리거 간의 거리를 세밀하게 조정할 수 있습니다.

'use client';

import { Button, Popover } from '@vapor-ui/core';

export default function PopoverOffset() {
    return (
        <div className="flex flex-col items-center gap-8 p-20">
            <div className="space-y-6">
                <h3 className="text-center text-sm font-medium text-foreground-hint">
                    오프셋 조정
                </h3>

                <div className="flex gap-4">
                    <Popover.Root>
                        <Popover.Trigger render={<Button variant="outline" />}>
                            기본 오프셋
                        </Popover.Trigger>
                        <Popover.Popup>
                            <Popover.Title>기본 오프셋</Popover.Title>
                            <Popover.Description>
                                기본 8px 오프셋이 적용된 팝오버입니다.
                            </Popover.Description>
                        </Popover.Popup>
                    </Popover.Root>

                    <Popover.Root>
                        <Popover.Trigger render={<Button variant="outline" />}>
                            사이드 오프셋 16px
                        </Popover.Trigger>
                        <Popover.Popup
                            positionerElement={<Popover.PositionerPrimitive sideOffset={16} />}
                        >
                            <Popover.Title>사이드 오프셋 16px</Popover.Title>
                            <Popover.Description>
                                트리거로부터 16px 떨어진 팝오버입니다.
                            </Popover.Description>
                        </Popover.Popup>
                    </Popover.Root>

                    <Popover.Root>
                        <Popover.Trigger render={<Button variant="outline" />}>
                            정렬 오프셋 20px
                        </Popover.Trigger>
                        <Popover.Popup
                            positionerElement={<Popover.PositionerPrimitive alignOffset={1000} />}
                        >
                            <Popover.Title>정렬 오프셋 100px</Popover.Title>
                            <Popover.Description>
                                정렬 축에서 100px 이동한 팝오버입니다.
                            </Popover.Description>
                        </Popover.Popup>
                    </Popover.Root>

                    <Popover.Root>
                        <Popover.Trigger render={<Button variant="outline" />}>
                            복합 오프셋
                        </Popover.Trigger>
                        <Popover.Popup
                            positionerElement={
                                <Popover.PositionerPrimitive sideOffset={24} alignOffset={-100} />
                            }
                        >
                            <Popover.Title>복합 오프셋</Popover.Title>
                            <Popover.Description>
                                사이드 24px, 정렬 -100px 오프셋이 적용된 팝오버입니다.
                            </Popover.Description>
                        </Popover.Popup>
                    </Popover.Root>
                </div>
            </div>
        </div>
    );
}

Examples


Content Variations

팝오버는 간단한 텍스트부터 복잡한 상호작용 요소까지 다양한 콘텐츠를 담을 수 있습니다.

'use client';

import { Button, Popover } from '@vapor-ui/core';

export default function PopoverPopup() {
    return (
        <div className="flex flex-wrap gap-4 p-20">
            <Popover.Root>
                <Popover.Trigger render={<Button variant="outline" />}>
                    간단한 텍스트
                </Popover.Trigger>
                <Popover.Popup>간단한 팝오버 메시지입니다.</Popover.Popup>
            </Popover.Root>

            <Popover.Root>
                <Popover.Trigger render={<Button variant="outline" />}>제목과 설명</Popover.Trigger>
                <Popover.Popup>
                    <Popover.Title>알림</Popover.Title>
                    <Popover.Description>
                        새로운 업데이트가 있습니다. 확인해보세요.
                    </Popover.Description>
                </Popover.Popup>
            </Popover.Root>

            <Popover.Root>
                <Popover.Trigger render={<Button variant="outline" />}>
                    상호작용 콘텐츠
                </Popover.Trigger>
                <Popover.Popup>
                    <Popover.Title>설정</Popover.Title>
                    <Popover.Description>원하는 설정을 선택하세요.</Popover.Description>
                    <div className="mt-4 space-y-2">
                        <Button size="sm" className="w-full">
                            옵션 1
                        </Button>
                        <Button size="sm" variant="outline" className="w-full">
                            옵션 2
                        </Button>
                    </div>
                </Popover.Popup>
            </Popover.Root>
        </div>
    );
}

Props Table


Popover.Root

Popover의 루트 컨테이너로, 전체 Popover 컴포넌트의 상태와 동작을 관리합니다.

PropDefaultType
open?
undefined
boolean
defaultOpen?
false
boolean
onOpenChange?
undefined
(open: boolean, event?: Event, reason?: string) => void
modal?
true
boolean{ trapFocus?: boolean }
openOnHover?
false
boolean
delay?
0
number{ open?: number; close?: number }

Popover.Trigger

Popover를 여는 트리거 요소입니다.

PropDefaultType
render?
undefined
React.ReactElement(props: TriggerProps, state: TriggerState) => React.ReactElement
disabled?
false
boolean

Popover.Popup

Popover의 실제 콘텐츠를 담는 컨테이너입니다. Portal과 Positioner를 조합하여 구성됩니다.

PropDefaultType
portalElement?
undefined
React.ReactElement
positionerElement?
undefined
React.ReactElement
className?
undefined
string

Popover.PortalPrimitive

Popover를 DOM의 다른 위치에 렌더링하는 포털 컴포넌트입니다.

PropDefaultType
container?
document.body
HTMLElement() => HTMLElementnull
keepMounted?
false
boolean

Popover.PositionerPrimitive

Popover의 위치를 설정하는 컴포넌트입니다.

PropDefaultType
side?
'bottom'
'top''right''bottom''left'
align?
'center'
'start''center''end'
sideOffset?
8
number(side: Side) => number
alignOffset?
0
number(side: Side) => number
collisionPadding?
8
number{ top?: number; right?: number; bottom?: number; left?: number }
collisionAvoidance?
true
boolean{ boundary?: HTMLElement; rootBoundary?: 'viewport' | 'document'; padding?: number }
arrowPadding?
4
number
sticky?
false
boolean'partial'

Popover.PopupPrimitive

Popover의 실제 팝업 콘텐츠 영역입니다.

PropDefaultType
className?
undefined
string
style?
undefined
CSSProperties
render?
undefined
React.ReactElement(props: PopupProps, state: PopupState) => React.ReactElement

Popover.Title

Popover의 제목을 표시하는 컴포넌트입니다.

PropDefaultType
render?
undefined
React.ReactElement(props: TitleProps) => React.ReactElement

Popover.Description

Popover의 설명을 표시하는 컴포넌트입니다.

PropDefaultType
render?
undefined
React.ReactElement(props: DescriptionProps) => React.ReactElement

Popover.Close

Popover를 닫는 버튼 컴포넌트입니다.

PropDefaultType
render?
undefined
React.ReactElement(props: CloseProps) => React.ReactElement