팝오버
팝오버 (Popover)
추가 정보나 동작을 제공하는 간단한 팝업 메뉴예요. Tooltip과 비교하면 정보 외에도 링크나 버튼 같은 동작 요소를 함께 넣을 수 있어요.
출처: 문서
본문
언제 사용하나요 (When To Use)
- 추가 정보나 동작을 제공하는 간단한 팝업 메뉴로 사용해요.
Tooltip과 달리 정보 외에 링크나 버튼 같은 동작 요소도 넣을 수 있어요.
예시 (Examples)
기본 (Basic)
가장 기본적인 예시예요. 떠 있는 레이어의 크기는 콘텐츠 영역에 따라 달라져요.
import React from 'react';
import { Button, Popover } from 'antd';
const content = (
<div>
<p style={{ margin: 0 }}>Content</p>
<p style={{ margin: 0 }}>Content</p>
</div>
);
const App: React.FC = () => (
<Popover content={content} title="Title">
<Button type="primary">Hover me</Button>
</Popover>
);
export default App;
세 가지 트리거 방식 (Three ways to trigger)
마우스 클릭, 포커스, 마우스를 올리는 방식으로 트리거할 수 있어요.
import React from 'react';
import { Button, Popover, Space } from 'antd';
const content = (
<div>
<p>Content</p>
<p>Content</p>
</div>
);
const App: React.FC = () => (
<Space wrap>
<Popover content={content} title="Title" trigger="hover">
<Button>Hover me</Button>
</Popover>
<Popover content={content} title="Title" trigger="focus">
<Button>Focus me</Button>
</Popover>
<Popover content={content} title="Title" trigger="click">
<Button>Click me</Button>
</Popover>
</Space>
);
export default App;
배치 (Placement)
12가지 placement 옵션이 있어요.
import React from 'react';
import { Button, ConfigProvider, Flex, Popover } from 'antd';
const text = <span>Title</span>;
const content = (
<div>
<p>Content</p>
<p>Content</p>
</div>
);
const buttonWidth = 80;
const App: React.FC = () => (
<ConfigProvider button={{ style: { width: buttonWidth, margin: 4 } }}>
<Flex vertical justify="center" align="center" className="demo">
<Flex justify="center" align="center" style={{ whiteSpace: 'nowrap' }}>
<Popover placement="topLeft" title={text} content={content}>
<Button>TL</Button>
</Popover>
<Popover placement="top" title={text} content={content}>
<Button>Top</Button>
</Popover>
<Popover placement="topRight" title={text} content={content}>
<Button>TR</Button>
</Popover>
</Flex>
<Flex style={{ width: buttonWidth * 5 + 32 }} justify="space-between" align="center">
<Flex align="center" vertical>
<Popover placement="leftTop" title={text} content={content}>
<Button>LT</Button>
</Popover>
<Popover placement="left" title={text} content={content}>
<Button>Left</Button>
</Popover>
<Popover placement="leftBottom" title={text} content={content}>
<Button>LB</Button>
</Popover>
</Flex>
<Flex align="center" vertical>
<Popover placement="rightTop" title={text} content={content}>
<Button>RT</Button>
</Popover>
<Popover placement="right" title={text} content={content}>
<Button>Right</Button>
</Popover>
<Popover placement="rightBottom" title={text} content={content}>
<Button>RB</Button>
</Popover>
</Flex>
</Flex>
<Flex justify="center" align="center" style={{ whiteSpace: 'nowrap' }}>
<Popover placement="bottomLeft" title={text} content={content}>
<Button>BL</Button>
</Popover>
<Popover placement="bottom" title={text} content={content}>
<Button>Bottom</Button>
</Popover>
<Popover placement="bottomRight" title={text} content={content}>
<Button>BR</Button>
</Popover>
</Flex>
</Flex>
</ConfigProvider>
);
export default App;
화살표 (Arrow)
arrow로 화살표를 숨길 수 있어요.
import React, { useMemo, useState } from 'react';
import { Button, ConfigProvider, Flex, Popover, Segmented } from 'antd';
import type { PopoverProps } from 'antd';
const text = <span>Title</span>;
const buttonWidth = 80;
const content = (
<div>
<p>Content</p>
<p>Content</p>
</div>
);
const App: React.FC = () => {
const [arrow, setArrow] = useState<'Show' | 'Hide' | 'Center'>('Show');
const mergedArrow = useMemo<PopoverProps['arrow']>(() => {
if (arrow === 'Hide') {
return false;
}
if (arrow === 'Show') {
return true;
}
return {
pointAtCenter: true,
};
}, [arrow]);
return (
<ConfigProvider button={{ style: { width: buttonWidth, margin: 4 } }}>
<Segmented
options={['Show', 'Hide', 'Center']}
onChange={setArrow}
style={{ marginBottom: 24 }}
/>
<Flex vertical justify="center" align="center" className="demo">
<Flex justify="center" align="center" style={{ whiteSpace: 'nowrap' }}>
<Popover placement="topLeft" title={text} content={content} arrow={mergedArrow}>
<Button>TL</Button>
</Popover>
<Popover placement="top" title={text} content={content} arrow={mergedArrow}>
<Button>Top</Button>
</Popover>
<Popover placement="topRight" title={text} content={content} arrow={mergedArrow}>
<Button>TR</Button>
</Popover>
</Flex>
<Flex style={{ width: buttonWidth * 5 + 32 }} justify="space-between" align="center">
<Flex align="center" vertical>
<Popover placement="leftTop" title={text} content={content} arrow={mergedArrow}>
<Button>LT</Button>
</Popover>
<Popover placement="left" title={text} content={content} arrow={mergedArrow}>
<Button>Left</Button>
</Popover>
<Popover placement="leftBottom" title={text} content={content} arrow={mergedArrow}>
<Button>LB</Button>
</Popover>
</Flex>
<Flex align="center" vertical>
<Popover placement="rightTop" title={text} content={content} arrow={mergedArrow}>
<Button>RT</Button>
</Popover>
<Popover placement="right" title={text} content={content} arrow={mergedArrow}>
<Button>Right</Button>
</Popover>
<Popover placement="rightBottom" title={text} content={content} arrow={mergedArrow}>
<Button>RB</Button>
</Popover>
</Flex>
</Flex>
<Flex justify="center" align="center" style={{ whiteSpace: 'nowrap' }}>
<Popover placement="bottomLeft" title={text} content={content} arrow={mergedArrow}>
<Button>BL</Button>
</Popover>
<Popover placement="bottom" title={text} content={content} arrow={mergedArrow}>
<Button>Bottom</Button>
</Popover>
<Popover placement="bottomRight" title={text} content={content} arrow={mergedArrow}>
<Button>BR</Button>
</Popover>
</Flex>
</Flex>
</ConfigProvider>
);
};
export default App;
자동 이동 (Auto Shift)
Popover가 화면 가장자리에 가까워지면 팝업과 화살표 위치를 자동으로 조정해요. 제한을 초과하면 화면 밖으로 나갈 수 있어요.
import React from 'react';
import { Button, Popover } from 'antd';
const style: React.CSSProperties = {
width: '300vw',
height: '300vh',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
};
const App: React.FC = () => {
React.useEffect(() => {
document.documentElement.scrollTop = document.documentElement.clientHeight;
document.documentElement.scrollLeft = document.documentElement.clientWidth;
}, []);
return (
<div style={style}>
<Popover content="Thanks for using antd. Have a nice day !" open>
<Button type="primary">Scroll The Window</Button>
</Popover>
</div>
);
};
export default App;
대화상자 닫기 제어 (Controlling the close of the dialog)
open prop으로 카드 표시를 제어할 수 있어요.
import React, { useState } from 'react';
import { Button, Popover } from 'antd';
const App: React.FC = () => {
const [open, setOpen] = useState(false);
const hide = () => {
setOpen(false);
};
const handleOpenChange = (newOpen: boolean) => {
setOpen(newOpen);
};
return (
<Popover
content={<a onClick={hide}>Close</a>}
title="Title"
trigger="click"
open={open}
onOpenChange={handleOpenChange}
>
<Button type="primary">Click me</Button>
</Popover>
);
};
export default App;
hover와 click 팝오버 (Hover with click popover)
다음 예시는 hover와 click이 모두 가능한 팝오버를 만드는 방법이에요.
import React, { useState } from 'react';
import { Button, Popover } from 'antd';
const hoverContent = <div>This is hover content.</div>;
const clickContent = <div>This is click content.</div>;
const App: React.FC = () => {
const [clicked, setClicked] = useState(false);
const [hovered, setHovered] = useState(false);
const hide = () => {
setClicked(false);
setHovered(false);
};
const handleHoverChange = (open: boolean) => {
setHovered(open);
setClicked(false);
};
const handleClickChange = (open: boolean) => {
setHovered(false);
setClicked(open);
};
return (
<Popover
style={{ width: 500 }}
content={hoverContent}
title="Hover title"
trigger="hover"
open={hovered}
onOpenChange={handleHoverChange}
>
<Popover
content={
<div>
{clickContent}
<a onClick={hide}>Close</a>
</div>
}
title="Click title"
trigger="click"
open={clicked}
onOpenChange={handleClickChange}
>
<Button>Hover and click</Button>
</Popover>
</Popover>
);
};
export default App;
시맨틱 DOM 스타일링 (Custom semantic dom styling)
classNames와 styles로 객체나 함수를 전달해 Popover의 시맨틱 DOM 스타일을 커스터마이즈할 수 있어요.
import React from 'react';
import { Button, Flex, Popover } from 'antd';
import type { GetProp, PopoverProps } from 'antd';
import { createStaticStyles } from 'antd-style';
const classNames = createStaticStyles(({ css }) => ({
container: css`
padding: 10px;
`,
}));
const styles: PopoverProps['styles'] = {
container: {
background: '#eee',
boxShadow: 'inset 5px 5px 3px #fff, inset -5px -5px 3px #ddd, 0 0 3px rgba(0,0,0,0.2)',
},
content: {
color: '#262626',
},
};
const stylesFn: PopoverProps['styles'] = (info): GetProp<PopoverProps, 'styles', 'Return'> => {
if (!info.props.arrow) {
return {
container: {
backgroundColor: 'rgba(53, 71, 125, 0.8)',
padding: 12,
borderRadius: 4,
},
content: {
color: '#fff',
},
};
}
};
const App: React.FC = () => {
return (
<Flex gap="medium">
<Popover content="Object text" classNames={classNames} styles={styles} arrow={false}>
<Button>Object Style</Button>
</Popover>
<Popover content="Function text" classNames={classNames} styles={stylesFn} arrow={false}>
<Button type="primary">Function Style</Button>
</Popover>
</Flex>
);
};
export default App;
API
공통 props는 Common props를 참고해요.
| 속성 (Property) | 설명 (Description) | 타입 (Type) | 기본값 (Default value) | 버전 (Version) | 글로벌 설정 |
|---|---|---|---|---|---|
| classNames | 컴포넌트 내부의 각 시맨틱 구조에 대한 class를 지정해요. 객체 또는 함수를 지원해요. | Record<SemanticDOM, string> | (info: { props })=> Record<SemanticDOM, string> | - | 5.23.0 | |
| content | 카드의 콘텐츠예요. | ReactNode | () => ReactNode | - | × | |
| title | 카드의 제목이에요. | ReactNode | () => ReactNode | - | × | |
| styles | 컴포넌트 내부의 각 시맨틱 구조에 대한 인라인 스타일을 지정해요. 객체 또는 함수를 지원해요. | Record<SemanticDOM, CSSProperties> | (info: { props })=> Record<SemanticDOM, CSSProperties> | - | 5.23.0 |
공통 API는 Tooltip 문서의 공유 props를 참고해요. (shared props embed)
참고 (Note)
Popover의 자식 노드가 onMouseEnter, onMouseLeave, onFocus, onClick 이벤트를 받을 수 있는지 확인해 주세요.
시맨틱 DOM (Semantic DOM)
시맨틱 DOM 구조는 https://ant.design/components/popover/semantic.md 에서 확인할 수 있어요.
디자인 토큰 (Design Token)
컴포넌트 토큰 (Popover) (Component Token)
| 토큰 이름 (Token Name) | 설명 (Description) | 타입 (Type) | 기본값 (Default Value) |
|---|---|---|---|
| titleMinWidth | Popover 제목의 최소 너비 | string | number | 177 |
| zIndexPopup | Popover의 z-index | number | 1030 |
글로벌 토큰 (Global Token)
| 토큰 이름 (Token Name) | 설명 (Description) | 타입 (Type) | 기본값 (Default Value) |
|---|---|---|---|
| borderRadiusLG | LG 크기 테두리 반경이에요. Card, Modal 등 큰 테두리 반경을 가진 컴포넌트에 사용돼요. | number | |
| borderRadiusXS | XS 크기 테두리 반경이에요. Segmented, Arrow 등 작은 테두리 반경을 가진 컴포넌트에 사용돼요. | number | |
| colorBgElevated | 팝업 레이어의 컨테이너 배경색이에요. 다크 모드에서는 이 토큰의 색이 colorBgContainer보다 약간 밝아요. 예: modal, pop-up, menu 등. |
string | |
| colorText | W3C 표준을 따르는 기본 텍스트 색이에요. 가장 어두운 중성색이기도 해요. | string | |
| colorTextHeading | 제목의 글자 색을 제어해요. | string | |
| fontFamily | Ant Design의 글꼴은 시스템의 기본 인터페이스 글꼴을 우선시하고, 화면 표시에 적합한 대체 글꼴 라이브러리를 제공해 플랫폼과 브라우저에 따라 가독성을 유지하며 친근하고 안정적이며 전문적인 특성을 반영해요. | string | |
| fontSize | 디자인 시스템에서 가장 널리 쓰이는 글자 크기로, 여기서 텍스트 그라데이션이 파생돼요. | number | |
| fontWeightStrong | 제목 컴포넌트(h1, h2, h3 등)나 선택된 항목의 글자 굵기를 제어해요. | number | |
| lineHeight | 텍스트의 줄 높이예요. | number | |
| motionDurationMid | 동작 속도, 중간 속도예요. 중간 요소의 애니메이션 상호작용에 사용돼요. | string | |
| motionEaseInOutCirc | 미리 정의된 모션 곡선이에요. | string | |
| motionEaseOutCirc | 미리 정의된 모션 곡선이에요. | string | |
| sizePopupArrow | 컴포넌트 화살표의 크기 | number |
FAQ
공통 FAQ는 Tooltip FAQ를 참고해요. 더 많은 질문은 Tooltip 문서를 확인해 주세요.