Popover
Popover
팝오버(Popover)는 요소 위에 뜨는 작은 팝업창으로, 버튼이나 링크를 클릭했을 때 상세 정보를 보여줄 때 사용해요. @chakra-ui/react에서 Popover 컴포넌트를 가져와 사용할 수 있어요.
출처: 문서
본문
사용법 (Usage)
import { Popover } from "@chakra-ui/react"
<Popover.Root>
<Popover.Trigger />
<Popover.Positioner>
<Popover.Content>
<Popover.CloseTrigger />
<Popover.Arrow>
<Popover.ArrowTip />
</Popover.Arrow>
<Popover.Body>
<Popover.Title />
</Popover.Body>
</Popover.Content>
</Popover.Positioner>
</Popover.Root>
단축 속성 (Shortcuts)
Popover는 자주 쓰는 사용 사례를 위한 단축 속성을 제공해요.
Arrow
Popover.Arrow는 기본적으로 내부에 Popover.ArrowTip 컴포넌트를 자동으로 렌더링해요.
이렇게 써도 동작해요:
<Popover.Arrow>
<Popover.ArrowTip />
</Popover.Arrow>
화살표 끝을 커스터마이즈할 필요가 없다면 이렇게 더 간결하게 쓸 수 있어요.
<Popover.Arrow />
예시 (Examples)
Controlled
open과 onOpenChange props를 사용해 팝오버의 표시 여부를 제어할 수 있어요.
여러 트리거 (Multiple Triggers)
버튼마다 팝오버를 하나씩 만들지 마세요. 하나의 Root 아래 각 Trigger에 value를 넣어주세요. 다른 트리거를 클릭하면 같은 팝오버가 그 위치로 이동해요.
Root의 triggerValue와 onTriggerValueChange로 활성 트리거를 추적할 수 있어요. 대상이 버튼이 아닌 경우에는 positioning.getAnchorRect를 사용하세요.
크기 (Sizes)
size prop을 사용해 팝오버 컴포넌트의 크기를 바꿀 수 있어요.
Lazy Mount
lazyMounted와 unmountOnExit prop을 사용해 팝오버 콘텐츠가 열릴 때까지 마운트를 지연할 수 있어요.
위치 (Placement)
positioning.placement prop을 사용해 내부의 floating-ui 위치 계산 로직을 설정할 수 있어요.
오프셋 (Offset)
positioning.offset prop을 사용해 팝오버 콘텐츠의 위치를 조정할 수 있어요.
같은 너비 (Same Width)
positioning.sameWidth prop을 사용해 팝오버 콘텐츠가 트리거와 같은 너비가 되도록 할 수 있어요.
중첩 팝오버 (Nested Popover)
팝오버 안에 팝오버, 셀렉트, 메뉴 같은 플로팅 요소를 중첩할 때는, 이들을 문서의 body로 포털링(portalling)하지 않는 것이 좋아요.
-<Portal>
<Popover.Positioner>
<Popover.Content>
{/* ... */}
</Popover.Content>
</Popover.Positioner>
-</Portal>
초기 포커스 (Initial Focus)
initialFocusEl prop을 사용해 팝오버 콘텐츠의 초기 포커스 위치를 설정할 수 있어요.
폼 (Form)
팝오버 안에 폼이 있는 예시는 다음과 같아요.
커스텀 배경 (Custom Background)
--popover-bg CSS 변수를 사용해 팝오버 콘텐츠와 화살표의 배경색을 바꿀 수 있어요.
다이얼로그에서 열기 (Open From Dialog)
Dialog 안에서 Popover를 사용하려면, Popover.Positioner를 문서의 body로 포털링하지 않아야 해요.
-<Portal>
<Popover.Positioner>
<Popover.Content>
{/* ... */}
</Popover.Content>
</Popover.Positioner>
-</Portal>
Dialog에 scrollBehavior="inside"를 설정했다면 다음을 처리해야 해요:
- 팝오버가 다이얼로그에 잘리지 않도록 팝오버 위치를
fixed로 설정해요. - 트리거가 화면 밖으로 스크롤되면 팝오버를 숨기도록
hideWhenDetached를true로 설정해요.
<Popover.Root positioning={{ strategy: "fixed", hideWhenDetached: true }}>
{/* ... */}
</Popover.Root>
가이드 (Guide)
팝오버 컨텍스트 접근 (Accessing popover context)
usePopoverContext를 사용하면 팝오버 안의 어떤 컴포넌트에서든 팝오버의 상태와 메서드에 접근할 수 있어요.
import { usePopoverContext } from "@chakra-ui/react"
const PopoverStatus = () => {
const popover = usePopoverContext()
return <div>Popover is {popover.open ? "open" : "closed"}</div>
}
const MyPopover = () => (
<Popover.Root>
<Popover.Trigger>Open</Popover.Trigger>
<Popover.Positioner>
<Popover.Content>
<PopoverStatus />
</Popover.Content>
</Popover.Positioner>
</Popover.Root>
)
프로그래밍 방식으로 닫기 (Closing programmatically)
컨텍스트의 setOpen(false)를 사용해 팝오버를 프로그래밍 방식으로 닫을 수 있어요.
import { usePopoverContext } from "@chakra-ui/react"
const CloseButton = () => {
const popover = usePopoverContext()
return <Button onClick={() => popover.setOpen(false)}>Close Popover</Button>
}
const MyPopover = () => (
<Popover.Root>
<Popover.Trigger>Open</Popover.Trigger>
<Popover.Positioner>
<Popover.Content>
<CloseButton />
</Popover.Content>
</Popover.Positioner>
</Popover.Root>
)
ref 기반 위치 지정 (Positioning based on ref)
positioning.getAnchorRect()를 사용해 커스텀 요소의 ref를 기준으로 팝오버를 위치시킬 수 있어요.
import { useRef } from "react"
const MyPopover = () => {
const anchorRef = useRef<HTMLDivElement>(null)
return (
<>
<div ref={anchorRef}>Anchor Element</div>
<Popover.Root
positioning={{
getAnchorRect() {
return anchorRef.current?.getBoundingClientRect()
},
}}
>
<Popover.Trigger>Open</Popover.Trigger>
<Popover.Positioner>
<Popover.Content>
<Popover.Body>
This popover is anchored to the div above
</Popover.Body>
</Popover.Content>
</Popover.Positioner>
</Popover.Root>
</>
)
}
Props
Popover의 여러 파트(Root, Trigger 등)별로 사용 가능한 props는 공식 문서에서 확인할 수 있어요.