투어 가이드
투어 가이드 (Tour)
사용자를 제품 전반에 걸쳐 안내해 주는 투어 가이드 컴포넌트입니다. 주요 기능을 단계별로 소개할 때 사용해요.
출처: 문서
본문
언제 사용하나요 (When To Use)
사용자를 제품 전반에 걸쳐 안내하고 싶을 때 사용합니다.
예제 (Examples)
기본 (Basic)
가장 기본적인 사용법입니다.
import React, { useRef, useState } from 'react';
import { EllipsisOutlined } from '@ant-design/icons';
import { Button, Divider, Space, Tour } from 'antd';
import type { TourProps } from 'antd';
const App: React.FC = () => {
const ref1 = useRef(null);
const ref2 = useRef(null);
const ref3 = useRef(null);
const [open, setOpen] = useState<boolean>(false);
const steps: TourProps['steps'] = [
{
title: 'Upload File',
description: 'Put your files here.',
cover: (
<img
draggable={false}
alt="tour.png"
src="https://user-images.githubusercontent.com/5378891/197385811-55df8480-7ff4-44bd-9d43-a7dade598d70.png"
/>
),
target: () => ref1.current,
},
{
title: 'Save',
description: 'Save your changes.',
target: () => ref2.current,
},
{
title: 'Other Actions',
description: 'Click to see other actions.',
target: () => ref3.current,
},
];
return (
<>
<Button type="primary" onClick={() => setOpen(true)}>
Begin Tour
</Button>
<Divider />
<Space>
<Button ref={ref1}>Upload</Button>
<Button ref={ref2} type="primary">
Save
</Button>
<Button ref={ref3} icon={<EllipsisOutlined />} />
</Space>
<Tour open={open} onClose={() => setOpen(false)} steps={steps} />
</>
);
};
export default App;
비모달 (Non-modal)
mask={false}를 사용해 Tour를 비모달로 만듭니다. 이때 type="primary"와 함께 사용해 가이드 자체를 강조하는 것을 권장합니다.
import React, { useRef, useState } from 'react';
import { EllipsisOutlined } from '@ant-design/icons';
import { Button, Divider, Space, Tour } from 'antd';
import type { TourProps } from 'antd';
const App: React.FC = () => {
const ref1 = useRef(null);
const ref2 = useRef(null);
const ref3 = useRef(null);
const [open, setOpen] = useState<boolean>(false);
const steps: TourProps['steps'] = [
{
title: 'Upload File',
description: 'Put your files here.',
cover: (
<img
draggable={false}
alt="tour.png"
src="https://user-images.githubusercontent.com/5378891/197385811-55df8480-7ff4-44bd-9d43-a7dade598d70.png"
/>
),
target: () => ref1.current,
},
{
title: 'Save',
description: 'Save your changes.',
target: () => ref2.current,
},
{
title: 'Other Actions',
description: 'Click to see other actions.',
target: () => ref3.current,
},
];
return (
<>
<Button type="primary" onClick={() => setOpen(true)}>
Begin non-modal Tour
</Button>
<Divider />
<Space>
<Button ref={ref1}>Upload</Button>
<Button ref={ref2} type="primary">
Save
</Button>
<Button ref={ref3} icon={<EllipsisOutlined />} />
</Space>
<Tour open={open} onClose={() => setOpen(false)} mask={false} type="primary" steps={steps} />
</>
);
};
export default App;
배치 (Placement)
대상 기준 가이드의 배치를 변경합니다. 12가지 배치가 있습니다. target={null}이면 가이드가 중앙에 표시됩니다.
import React, { useRef, useState } from 'react';
import { Button, Tour } from 'antd';
import type { TourProps } from 'antd';
const App: React.FC = () => {
const ref = useRef(null);
const [open, setOpen] = useState<boolean>(false);
const steps: TourProps['steps'] = [
{
title: 'Center',
description: 'Displayed in the center of screen.',
target: null,
},
{
title: 'Right',
description: 'On the right of target.',
placement: 'right',
target: () => ref.current,
},
{
title: 'Top',
description: 'On the top of target.',
placement: 'top',
target: () => ref.current,
},
];
return (
<>
<Button type="primary" onClick={() => setOpen(true)} ref={ref}>
Begin Tour
</Button>
<Tour open={open} onClose={() => setOpen(false)} steps={steps} />
</>
);
};
export default App;
커스텀 마스크 스타일 (Custom mask style)
커스텀 마스크 스타일입니다.
import React, { useRef, useState } from 'react';
import { EllipsisOutlined } from '@ant-design/icons';
import { Button, Divider, Space, Tour } from 'antd';
import type { TourProps } from 'antd';
const App: React.FC = () => {
const ref1 = useRef(null);
const ref2 = useRef(null);
const ref3 = useRef(null);
const [open, setOpen] = useState<boolean>(false);
const steps: TourProps['steps'] = [
{
title: 'Upload File',
description: 'Put your files here.',
cover: (
<img
draggable={false}
alt="tour.png"
src="https://user-images.githubusercontent.com/5378891/197385811-55df8480-7ff4-44bd-9d43-a7dade598d70.png"
/>
),
target: () => ref1.current,
},
{
title: 'Save',
description: 'Save your changes.',
target: () => ref2.current,
mask: {
style: {
boxShadow: 'inset 0 0 15px #fff',
},
color: 'rgba(40, 0, 255, .4)',
},
},
{
title: 'Other Actions',
description: 'Click to see other actions.',
target: () => ref3.current,
mask: false,
},
];
return (
<>
<Button type="primary" onClick={() => setOpen(true)}>
Begin Tour
</Button>
<Divider />
<Space>
<Button ref={ref1}>Upload</Button>
<Button ref={ref2} type="primary">
Save
</Button>
<Button ref={ref3} icon={<EllipsisOutlined />} />
</Space>
<Tour
open={open}
onClose={() => setOpen(false)}
steps={steps}
mask={{
style: {
boxShadow: 'inset 0 0 15px #333',
},
color: 'rgba(80, 255, 255, .4)',
}}
/>
</>
);
};
export default App;
커스텀 인디케이터 (Custom indicator)
커스텀 인디케이터입니다.
import React, { useRef, useState } from 'react';
import { EllipsisOutlined } from '@ant-design/icons';
import type { GetRef, TourProps } from 'antd';
import { Button, Divider, Space, Tour } from 'antd';
const App: React.FC = () => {
const ref1 = useRef<GetRef<typeof Button>>(null);
const ref2 = useRef<GetRef<typeof Button>>(null);
const ref3 = useRef<GetRef<typeof Button>>(null);
const [open, setOpen] = useState<boolean>(false);
const steps: TourProps['steps'] = [
{
title: 'Upload File',
description: 'Put your files here.',
target: () => ref1.current!,
},
{
title: 'Save',
description: 'Save your changes.',
target: () => ref2.current!,
},
{
title: 'Other Actions',
description: 'Click to see other actions.',
target: () => ref3.current!,
},
];
return (
<>
<Button type="primary" onClick={() => setOpen(true)}>
Begin Tour
</Button>
<Divider />
<Space>
<Button ref={ref1}>Upload</Button>
<Button ref={ref2} type="primary">
Save
</Button>
<Button ref={ref3} icon={<EllipsisOutlined />} />
</Space>
<Tour
open={open}
onClose={() => setOpen(false)}
steps={steps}
indicatorsRender={(current, total) => (
<span>
{current + 1} / {total}
</span>
)}
/>
</>
);
};
export default App;
커스텀 액션 (Custom action)
커스텀 액션입니다.
import React, { useRef, useState } from 'react';
import { EllipsisOutlined } from '@ant-design/icons';
import type { GetRef, TourProps } from 'antd';
import { Button, Divider, Space, Tour } from 'antd';
const App: React.FC = () => {
const ref1 = useRef<GetRef<typeof Button>>(null);
const ref2 = useRef<GetRef<typeof Button>>(null);
const ref3 = useRef<GetRef<typeof Button>>(null);
const [open, setOpen] = useState<boolean>(false);
const steps: TourProps['steps'] = [
{
title: 'Upload File',
description: 'Put your files here.',
target: () => ref1.current!,
},
{
title: 'Save',
description: 'Save your changes.',
target: () => ref2.current!,
},
{
title: 'Other Actions',
description: 'Click to see other actions.',
target: () => ref3.current!,
},
];
return (
<>
<Button type="primary" onClick={() => setOpen(true)}>
Begin Tour
</Button>
<Divider />
<Space>
<Button ref={ref1}>Upload</Button>
<Button ref={ref2} type="primary">
Save
</Button>
<Button ref={ref3} icon={<EllipsisOutlined />} />
</Space>
<Tour
open={open}
onClose={() => setOpen(false)}
steps={steps}
actionsRender={(originNode, { current, total }) => (
<>
{current !== total - 1 && (
<Button
size="small"
onClick={() => {
setOpen(false);
}}
>
Skip
</Button>
)}
{originNode}
</>
)}
/>
</>
);
};
export default App;
커스텀 강조 영역 스타일 (Custom highlighted area style)
gap을 사용해 강조 영역의 반경과 강조 영역·요소 사이의 오프셋을 제어합니다.
- 두 방향으로 개별적으로 오프셋을 설정하거나 배열 타입의
offset을 지원하는 것은5.9.0부터 가능합니다.
import React, { useRef, useState } from 'react';
import { Button, Col, Row, Slider, Space, Tour, Typography } from 'antd';
import type { TourProps } from 'antd';
const { Text } = Typography;
const App: React.FC = () => {
const tourNodeRef = useRef(null);
const [radius, setRadius] = useState(8);
const [offsetX, setOffsetX] = useState(2);
const [offsetY, setOffsetY] = useState(2);
const [offset, setOffset] = useState(2);
const [open, setOpen] = useState(false);
const [offsetDirection, setOffsetDirection] = useState<'both' | 'individual'>('individual');
const steps: TourProps['steps'] = [
{
title: 'Upload File',
description: 'Put your files here.',
cover: (
<img
draggable={false}
alt="tour.png"
src="https://user-images.githubusercontent.com/5378891/197385811-55df8480-7ff4-44bd-9d43-a7dade598d70.png"
/>
),
target: () => tourNodeRef.current,
},
];
const offsetGap =
offsetDirection === 'both'
? { offset }
: {
offset: [offsetX, offsetY] as [number, number],
};
return (
<div ref={tourNodeRef}>
<Button type="primary" onClick={() => setOpen(true)}>
Begin Tour
</Button>
<Space style={{ display: 'flex', marginTop: 12 }} vertical>
<Row>
<Col span={6}>
<Text>Radius:</Text>
</Col>
<Col span={12}>
<Slider value={radius} onChange={(val) => val && setRadius(val)} />
</Col>
</Row>
<Row>
<Col span={6}>
<Text> offset:</Text>
</Col>
<Col span={12}>
<Slider
value={offset}
max={50}
onChange={(val) => val && setOffset(val)}
onFocus={() => setOffsetDirection('both')}
/>
</Col>
</Row>
<Row>
<Col span={6}>
<Text>Horizontal offset:</Text>
</Col>
<Col span={12}>
<Slider
value={offsetX}
max={50}
onChange={(val) => val && setOffsetX(val)}
onFocus={() => setOffsetDirection('individual')}
/>
</Col>
</Row>
<Row>
<Col span={6}>
<Text>Vertical offset:</Text>
</Col>
<Col span={12}>
<Slider
value={offsetY}
max={50}
onChange={(val) => val && setOffsetY(val)}
onFocus={() => setOffsetDirection('individual')}
/>
</Col>
</Row>
</Space>
<Tour
open={open}
onClose={() => setOpen(false)}
steps={steps}
gap={{ ...offsetGap, radius }}
/>
</div>
);
};
export default App;
커스텀 시맨틱 DOM 스타일링 (Custom semantic dom styling)
classNames와 styles에 객체 또는 함수를 넘겨서 Tour의 시맨틱 DOM 스타일을 커스터마이즈할 수 있습니다.
import React, { useRef, useState } from 'react';
import { Button, Divider, Flex, Space, Tour } from 'antd';
import type { GetProp, TourProps, TourStepProps } from 'antd';
import { createStaticStyles } from 'antd-style';
const btnProps: {
nextButtonProps: TourStepProps['nextButtonProps'];
prevButtonProps: TourStepProps['prevButtonProps'];
} = {
nextButtonProps: {
style: {
border: '1px solid #CDC1FF',
color: '#CDC1FF',
},
},
prevButtonProps: {
style: {
backgroundColor: '#CDC1FF',
color: '#fff',
},
},
};
const classNames = createStaticStyles(({ css }) => ({
root: css`
border-radius: 4px;
`,
section: css`
border-radius: 8px;
`,
}));
const stylesObject: TourProps['styles'] = {
mask: {
backgroundColor: 'rgba(0, 0, 0, 0.3)',
},
section: {
boxShadow: '0 4px 12px rgba(0, 0, 0, 0.15)',
border: '2px solid #4096ff',
},
cover: {
borderRadius: '12px 12px 0 0',
},
};
const stylesFunction: TourProps['styles'] = (info): GetProp<TourProps, 'styles', 'Return'> => {
if (info.props.type === 'primary') {
return {
mask: {
backgroundColor: 'rgba(0, 0, 0, 0.3)',
},
section: {
backgroundColor: 'rgb(205,193,255, 0.8)',
boxShadow: '0 4px 12px rgba(0, 0, 0, 0.15)',
},
cover: {
borderRadius: '12px 12px 0 0',
},
};
}
return {};
};
const App: React.FC = () => {
const ref1 = useRef<HTMLButtonElement | HTMLAnchorElement>(null);
const ref2 = useRef<HTMLButtonElement | HTMLAnchorElement>(null);
const ref3 = useRef<HTMLButtonElement | HTMLAnchorElement>(null);
const [open, setOpen] = useState<boolean>(false);
const [openFn, setOpenFn] = useState<boolean>(false);
const steps: TourProps['steps'] = [
{
title: 'Upload File',
description: 'Put your files here.',
cover: (
<img
alt="tour.png"
src="https://user-images.githubusercontent.com/5378891/197385811-55df8480-7ff4-44bd-9d43-a7dade598d70.png"
/>
),
target: () => ref1.current || document.body,
prevButtonProps: {},
},
{
title: 'Save',
description: 'Save your changes.',
target: () => ref2.current || document.body,
},
{
title: 'Other Actions',
description: 'Click to see other actions.',
target: () => ref3.current || document.body,
},
];
const sharedProps: TourProps = {
steps,
classNames,
arrow: false,
};
return (
<Flex vertical gap="medium">
<Flex gap="medium">
<Button type="primary" onClick={() => setOpen(true)}>
Begin Tour Object
</Button>
<Button type="primary" onClick={() => setOpenFn(true)}>
Begin Tour Function
</Button>
</Flex>
<Divider />
<Tour {...sharedProps} open={open} onClose={() => setOpen(false)} styles={stylesObject} />
<Tour
{...sharedProps}
steps={steps.map((s) => ({ ...s, ...btnProps }))}
type="primary"
open={openFn}
onClose={() => setOpenFn(false)}
styles={stylesFunction}
/>
<Space>
<Button ref={ref1} type="primary">
Upload
</Button>
<Button ref={ref2}>Save</Button>
<Button ref={ref3} type="dashed">
Other Actions
</Button>
</Space>
</Flex>
);
};
export default App;
API
Common props ref:Common props
Tour
| Property | Description | Type | Default | Version | Global Config |
|---|---|---|---|---|---|
| arrow | Whether to show the arrow, including the configuration whether to point to the center of the element | boolean | { pointAtCenter: boolean } |
true |
× | |
| classNames | Customize class for each semantic structure inside the component. Supports object or function. | Record<SemanticDOM, string> | (info: { props })=> Record<SemanticDOM, string> | - | 6.0.0 | |
| closeIcon | Customize close icon | React.ReactNode |
true |
5.9.0 | 5.14.0 |
| disabledInteraction | Disable interaction on highlighted area. | boolean |
false |
5.13.0 | × |
| gap | Control the radius of the highlighted area and the offset between highlighted area and the element. | { offset?: number | [number, number]; radius?: number } |
{ offset?: 6 ; radius?: 2 } |
5.0.0 (array type offset: 5.9.0) |
× |
| keyboard | Whether to enable keyboard shortcuts | boolean | true | 6.2.0 | × |
| placement | Position of the guide card relative to the target element | center | left | leftTop | leftBottom | right | rightTop | rightBottom | top | topLeft | topRight | bottom | bottomLeft | bottomRight |
bottom |
× | |
| onClose | Callback function on shutdown | Function |
- | × | |
| onFinish | Callback when the tour is finished | Function |
- | × | |
| mask | Whether to enable masking, change mask style and fill color by pass custom props | boolean | { style?: React.CSSProperties; color?: string; } |
true |
× | |
| type | Type, affects the background color and text color | default | primary |
default |
× | |
| open | Open tour | boolean |
- | × | |
| onChange | Callback when the step changes. Current is the previous step | (current: number) => void |
- | × | |
| current | What is the current step | number |
- | × | |
| scrollIntoViewOptions | support pass custom scrollIntoView options | boolean | ScrollIntoViewOptions |
true |
5.2.0 | × |
| styles | Customize inline style for each semantic structure inside the component. Supports object or function. | Record<SemanticDOM, CSSProperties> | (info: { props })=> Record<SemanticDOM, CSSProperties> | - | 6.0.0 | |
| indicatorsRender | custom indicator | (current: number, total: number) => ReactNode |
- | 5.2.0 | × |
| actionsRender | custom action | (originNode: ReactNode, info: { current: number, total: number }) => ReactNode |
- | 5.25.0 | × |
| zIndex | Tour's zIndex | number | 1001 | 5.3.0 | × |
| getPopupContainer | Set the rendering node of Tour floating layer | (node: HTMLElement) => HTMLElement |
body | 5.12.0 | × |
TourStep
| Property | Description | Type | Default | Version |
|---|---|---|---|---|
| target | Get the element the guide card points to. Empty makes it show in center of screen | () => HTMLElement | HTMLElement |
- | |
| arrow | Whether to show the arrow, including the configuration whether to point to the center of the element | boolean | { pointAtCenter: boolean} |
true |
|
| closeIcon | Customize close icon | React.ReactNode |
true |
5.9.0 |
| cover | Displayed pictures or videos | ReactNode |
- | |
| title | title | ReactNode |
- | |
| description | description | ReactNode |
- | |
| placement | Position of the guide card relative to the target element | center | left | leftTop | leftBottom | right | rightTop | rightBottom | top | topLeft | topRight | bottom | bottomLeft | bottomRight |
bottom |
|
| onClose | Callback function on shutdown | Function |
- | |
| mask | Whether to enable masking, change mask style and fill color by pass custom props, the default follows the mask property of Tour |
boolean | { style?: React.CSSProperties; color?: string; } |
true |
|
| type | Type, affects the background color and text color | default | primary |
default |
|
| nextButtonProps | Properties of the Next button | { children: ReactNode; onClick: Function } |
- | |
| prevButtonProps | Properties of the previous button | { children: ReactNode; onClick: Function } |
- | |
| scrollIntoViewOptions | support pass custom scrollIntoView options, the default follows the scrollIntoViewOptions property of Tour |
boolean | ScrollIntoViewOptions |
true |
5.2.0 |
시맨틱 DOM (Semantic DOM)
https://ant.design/components/tour/semantic.md
디자인 토큰 (Design Token)
컴포넌트 토큰 (Component Token - Tour)
| Token Name | Description | Type | Default Value |
|---|---|---|---|
| closeBtnSize | Close button size | number | 22 |
| primaryNextBtnHoverBg | Hover background color of next button in primary type | string | rgb(240,240,240) |
| primaryPrevBtnBg | Background color of previous button in primary type | string | rgba(255,255,255,0.15) |
| zIndexPopup | Tour popup z-index | number | 1070 |
글로벌 토큰 (Global Token)
| Token Name | Description | Type | Default Value |
|---|---|---|---|
| borderRadius | Border radius of base components | number | |
| borderRadiusLG | LG size border radius, used in some large border radius components, such as Card, Modal and other components. | number | |
| borderRadiusSM | SM size border radius, used in small size components, such as Button, Input, Select and other input components in small size | number | |
| borderRadiusXS | XS size border radius, used in some small border radius components, such as Segmented, Arrow and other components with small border radius. | number | |
| boxShadowTertiary | Control the tertiary box shadow style of an element. | string | |
| colorBgElevated | Container background color of the popup layer, in dark mode the color value of this token will be a little brighter than colorBgContainer. E.g: modal, pop-up, menu, etc. |
string | |
| colorBgTextActive | Control the background color of text in active state. | string | |
| colorBgTextHover | Control the background color of text in hover state. | string | |
| colorFill | The darkest fill color is used to distinguish between the second and third level of fill color, and is currently only used in the hover effect of Slider. | string | |
| colorIcon | Weak action. Such as allowClear or Alert close button |
string | |
| colorIconHover | Weak action hover color. Such as allowClear or Alert close button |
string | |
| colorPrimary | Brand color is one of the most direct visual elements to reflect the characteristics and communication of the product. After you have selected the brand color, we will automatically generate a complete color palette and assign it effective design semantics. | string | |
| colorPrimaryBorder | The stroke color under the main color gradient, used on the stroke of components such as Slider. | string | |
| colorText | Default text color which comply with W3C standards, and this color is also the darkest neutral color. | string | |
| colorTextLightSolid | Control the highlight color of text with background color, such as the text in Primary Button components. | string | |
| colorWhite | Pure white color don't changed by theme | string | |
| fontFamily | The font family of Ant Design prioritizes the default interface font of the system, and provides a set of alternative font libraries that are suitable for screen display to maintain the readability and readability of the font under different platforms and browsers, reflecting the friendly, stable and professional characteristics. | string | |
| fontSize | The most widely used font size in the design system, from which the text gradient will be derived. | number | |
| fontWeightStrong | Control the font weight of heading components (such as h1, h2, h3) or selected item. | number | |
| lineHeight | Line height of text. | number | |
| lineWidthFocus | Control the width of the line when the component is in focus state. | number | |
| marginXS | Control the margin of an element, with a small size. | number | |
| motionDurationMid | Motion speed, medium speed. Used for medium element animation interaction. | string | |
| motionDurationSlow | Motion speed, slow speed. Used for large element animation interaction. | string | |
| padding | Control the padding of the element. | number | |
| paddingXS | Control the extra small padding of the element. | number | |
| sizePopupArrow | The size of the component arrow | number |