mirror of
https://github.com/ant-design/ant-design.git
synced 2025-06-12 20:43:11 +08:00
feat: Tour add actionsRender prop (#53067)
* feat: Tour add buttonsRender prop * chore: Revert unnecessary format modify * fix(test): Update snapshots
This commit is contained in:
parent
b3af097e8c
commit
53965b88cf
@ -1,5 +1,178 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`renders components/tour/demo/actions-render.tsx extend context correctly 1`] = `
|
||||
Array [
|
||||
<button
|
||||
class="ant-btn ant-btn-primary ant-btn-color-primary ant-btn-variant-solid"
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
Begin Tour
|
||||
</span>
|
||||
</button>,
|
||||
<div
|
||||
class="ant-divider ant-divider-horizontal"
|
||||
role="separator"
|
||||
/>,
|
||||
<div
|
||||
class="ant-space ant-space-horizontal ant-space-align-center ant-space-gap-row-small ant-space-gap-col-small"
|
||||
>
|
||||
<div
|
||||
class="ant-space-item"
|
||||
>
|
||||
<button
|
||||
class="ant-btn ant-btn-default ant-btn-color-default ant-btn-variant-outlined"
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
Upload
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
class="ant-space-item"
|
||||
>
|
||||
<button
|
||||
class="ant-btn ant-btn-primary ant-btn-color-primary ant-btn-variant-solid"
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
Save
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
class="ant-space-item"
|
||||
>
|
||||
<button
|
||||
class="ant-btn ant-btn-default ant-btn-color-default ant-btn-variant-outlined ant-btn-icon-only"
|
||||
type="button"
|
||||
>
|
||||
<span
|
||||
class="ant-btn-icon"
|
||||
>
|
||||
<span
|
||||
aria-label="ellipsis"
|
||||
class="anticon anticon-ellipsis"
|
||||
role="img"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
data-icon="ellipsis"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M176 511a56 56 0 10112 0 56 56 0 10-112 0zm280 0a56 56 0 10112 0 56 56 0 10-112 0zm280 0a56 56 0 10112 0 56 56 0 10-112 0z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>,
|
||||
<div
|
||||
class="ant-tour ant-tour-placement-bottom"
|
||||
style="--arrow-x: 0px; --arrow-y: 0px; left: -1000vw; top: -1000vh; box-sizing: border-box; z-index: 1001;"
|
||||
>
|
||||
<div
|
||||
class="ant-tour-arrow"
|
||||
style="position: absolute; top: 0px; left: 0px;"
|
||||
/>
|
||||
<div
|
||||
class="ant-tour-content"
|
||||
>
|
||||
<div
|
||||
class="ant-tour-inner"
|
||||
>
|
||||
<button
|
||||
aria-label="Close"
|
||||
class="ant-tour-close"
|
||||
type="button"
|
||||
>
|
||||
<span
|
||||
aria-label="close"
|
||||
class="anticon anticon-close ant-tour-close-icon"
|
||||
role="img"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
data-icon="close"
|
||||
fill="currentColor"
|
||||
fill-rule="evenodd"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M799.86 166.31c.02 0 .04.02.08.06l57.69 57.7c.04.03.05.05.06.08a.12.12 0 010 .06c0 .03-.02.05-.06.09L569.93 512l287.7 287.7c.04.04.05.06.06.09a.12.12 0 010 .07c0 .02-.02.04-.06.08l-57.7 57.69c-.03.04-.05.05-.07.06a.12.12 0 01-.07 0c-.03 0-.05-.02-.09-.06L512 569.93l-287.7 287.7c-.04.04-.06.05-.09.06a.12.12 0 01-.07 0c-.02 0-.04-.02-.08-.06l-57.69-57.7c-.04-.03-.05-.05-.06-.07a.12.12 0 010-.07c0-.03.02-.05.06-.09L454.07 512l-287.7-287.7c-.04-.04-.05-.06-.06-.09a.12.12 0 010-.07c0-.02.02-.04.06-.08l57.7-57.69c.03-.04.05-.05.07-.06a.12.12 0 01.07 0c.03 0 .05.02.09.06L512 454.07l287.7-287.7c.04-.04.06-.05.09-.06a.12.12 0 01.07 0z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</button>
|
||||
<div
|
||||
class="ant-tour-header"
|
||||
>
|
||||
<div
|
||||
class="ant-tour-title"
|
||||
>
|
||||
Upload File
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="ant-tour-description"
|
||||
>
|
||||
Put your files here.
|
||||
</div>
|
||||
<div
|
||||
class="ant-tour-footer"
|
||||
>
|
||||
<div
|
||||
class="ant-tour-indicators"
|
||||
>
|
||||
<span
|
||||
class="ant-tour-indicator-active ant-tour-indicator"
|
||||
/>
|
||||
<span
|
||||
class="ant-tour-indicator"
|
||||
/>
|
||||
<span
|
||||
class="ant-tour-indicator"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="ant-tour-buttons"
|
||||
>
|
||||
<button
|
||||
class="ant-btn ant-btn-default ant-btn-color-default ant-btn-variant-outlined ant-btn-sm"
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
Skip
|
||||
</span>
|
||||
</button>
|
||||
<button
|
||||
class="ant-btn ant-btn-primary ant-btn-color-primary ant-btn-variant-solid ant-btn-sm ant-tour-next-btn"
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
Next
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>,
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`renders components/tour/demo/actions-render.tsx extend context correctly 2`] = `[]`;
|
||||
|
||||
exports[`renders components/tour/demo/basic.tsx extend context correctly 1`] = `
|
||||
Array [
|
||||
<button
|
||||
@ -25,7 +198,7 @@ Array [
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
Upload
|
||||
Upload
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
@ -726,7 +899,7 @@ Array [
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
Upload
|
||||
Upload
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
@ -899,7 +1072,7 @@ Array [
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
Upload
|
||||
Upload
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
|
@ -25,7 +25,84 @@ Array [
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
Upload
|
||||
Upload
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
class="ant-space-item"
|
||||
>
|
||||
<button
|
||||
class="ant-btn ant-btn-primary ant-btn-color-primary ant-btn-variant-solid"
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
Save
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
class="ant-space-item"
|
||||
>
|
||||
<button
|
||||
class="ant-btn ant-btn-default ant-btn-color-default ant-btn-variant-outlined ant-btn-icon-only"
|
||||
type="button"
|
||||
>
|
||||
<span
|
||||
class="ant-btn-icon"
|
||||
>
|
||||
<span
|
||||
aria-label="ellipsis"
|
||||
class="anticon anticon-ellipsis"
|
||||
role="img"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
data-icon="ellipsis"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M176 511a56 56 0 10112 0 56 56 0 10-112 0zm280 0a56 56 0 10112 0 56 56 0 10-112 0zm280 0a56 56 0 10112 0 56 56 0 10-112 0z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>,
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`renders components/tour/demo/actions-render.tsx correctly 1`] = `
|
||||
Array [
|
||||
<button
|
||||
class="ant-btn ant-btn-primary ant-btn-color-primary ant-btn-variant-solid"
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
Begin Tour
|
||||
</span>
|
||||
</button>,
|
||||
<div
|
||||
class="ant-divider ant-divider-horizontal"
|
||||
role="separator"
|
||||
/>,
|
||||
<div
|
||||
class="ant-space ant-space-horizontal ant-space-align-center ant-space-gap-row-small ant-space-gap-col-small"
|
||||
>
|
||||
<div
|
||||
class="ant-space-item"
|
||||
>
|
||||
<button
|
||||
class="ant-btn ant-btn-default ant-btn-color-default ant-btn-variant-outlined"
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
Upload
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
@ -385,7 +462,7 @@ Array [
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
Upload
|
||||
Upload
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
@ -462,7 +539,7 @@ Array [
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
Upload
|
||||
Upload
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
|
7
components/tour/demo/actions-render.md
Normal file
7
components/tour/demo/actions-render.md
Normal file
@ -0,0 +1,7 @@
|
||||
## zh-CN
|
||||
|
||||
自定义操作按钮。
|
||||
|
||||
## en-US
|
||||
|
||||
Custom action.
|
68
components/tour/demo/actions-render.tsx
Normal file
68
components/tour/demo/actions-render.tsx
Normal file
@ -0,0 +1,68 @@
|
||||
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;
|
@ -40,7 +40,7 @@ const App: React.FC = () => {
|
||||
</Button>
|
||||
<Divider />
|
||||
<Space>
|
||||
<Button ref={ref1}> Upload</Button>
|
||||
<Button ref={ref1}>Upload</Button>
|
||||
<Button ref={ref2} type="primary">
|
||||
Save
|
||||
</Button>
|
||||
|
@ -50,7 +50,7 @@ const App: React.FC = () => {
|
||||
<Divider />
|
||||
|
||||
<Space>
|
||||
<Button ref={ref1}> Upload</Button>
|
||||
<Button ref={ref1}>Upload</Button>
|
||||
<Button ref={ref2} type="primary">
|
||||
Save
|
||||
</Button>
|
||||
|
@ -43,7 +43,7 @@ const App: React.FC = () => {
|
||||
<Divider />
|
||||
|
||||
<Space>
|
||||
<Button ref={ref1}> Upload</Button>
|
||||
<Button ref={ref1}>Upload</Button>
|
||||
<Button ref={ref2} type="primary">
|
||||
Save
|
||||
</Button>
|
||||
|
@ -22,6 +22,7 @@ Use when you want to guide users through a product.
|
||||
<code src="./demo/placement.tsx">Placement</code>
|
||||
<code src="./demo/mask.tsx">Custom mask style</code>
|
||||
<code src="./demo/indicator.tsx">Custom indicator</code>
|
||||
<code src="./demo/actions-render.tsx" version="5.25.0">Custom action</code>
|
||||
<code src="./demo/gap.tsx">Custom highlighted area style</code>
|
||||
<code src="./demo/render-panel.tsx" debug>\_InternalPanelDoNotUseOrYouWillBeFired</code>
|
||||
|
||||
@ -46,6 +47,7 @@ Common props ref:[Common props](/docs/react/common-props)
|
||||
| current | What is the current step | `number` | - | |
|
||||
| scrollIntoViewOptions | support pass custom scrollIntoView options | `boolean \| ScrollIntoViewOptions` | `true` | 5.2.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 |
|
||||
|
||||
|
@ -22,6 +22,7 @@ const Tour: React.FC<TourProps> & { _InternalPanelDoNotUseOrYouWillBeFired: type
|
||||
type,
|
||||
rootClassName,
|
||||
indicatorsRender,
|
||||
actionsRender,
|
||||
steps,
|
||||
closeIcon,
|
||||
...restProps
|
||||
@ -66,6 +67,7 @@ const Tour: React.FC<TourProps> & { _InternalPanelDoNotUseOrYouWillBeFired: type
|
||||
stepProps={stepProps}
|
||||
current={stepCurrent}
|
||||
indicatorsRender={indicatorsRender}
|
||||
actionsRender={actionsRender}
|
||||
/>
|
||||
);
|
||||
|
||||
|
@ -23,6 +23,7 @@ tag: 5.0.0
|
||||
<code src="./demo/placement.tsx">位置</code>
|
||||
<code src="./demo/mask.tsx">自定义遮罩样式</code>
|
||||
<code src="./demo/indicator.tsx">自定义指示器</code>
|
||||
<code src="./demo/actions-render.tsx" version="5.25.0">自定义操作按钮</code>
|
||||
<code src="./demo/gap.tsx">自定义高亮区域的样式</code>
|
||||
<code src="./demo/render-panel.tsx" debug>\_InternalPanelDoNotUseOrYouWillBeFired</code>
|
||||
|
||||
@ -48,6 +49,7 @@ tag: 5.0.0
|
||||
| current | 当前处于哪一步 | `number` | - | |
|
||||
| scrollIntoViewOptions | 是否支持当前元素滚动到视窗内,也可传入配置指定滚动视窗的相关参数 | `boolean \| ScrollIntoViewOptions` | `true` | 5.2.0 |
|
||||
| indicatorsRender | 自定义指示器 | `(current: number, total: number) => ReactNode` | - | 5.2.0 |
|
||||
| actionsRender | 自定义操作按钮 | `(originNode: ReactNode, info: { current: number, total: number }) => ReactNode` | - | 5.25.0 |
|
||||
| zIndex | Tour 的层级 | number | 1001 | 5.3.0 |
|
||||
| getPopupContainer | 设置 Tour 浮层的渲染节点,默认是 body | `(node: HTMLElement) => HTMLElement` | body | 5.12.0 |
|
||||
|
||||
|
@ -9,6 +9,7 @@ export interface TourProps extends Omit<RCTourProps, 'renderPanel'> {
|
||||
prefixCls?: string;
|
||||
current?: number;
|
||||
indicatorsRender?: (current: number, total: number) => ReactNode;
|
||||
actionsRender?: TourStepProps['actionsRender'];
|
||||
type?: 'default' | 'primary'; // default type, affects the background color and text color
|
||||
}
|
||||
|
||||
@ -27,6 +28,7 @@ export interface TourStepProps extends RCTourStepProps {
|
||||
style?: React.CSSProperties;
|
||||
};
|
||||
indicatorsRender?: (current: number, total: number) => ReactNode;
|
||||
actionsRender?: (originNode: ReactNode, info: { current: number; total: number }) => ReactNode;
|
||||
type?: 'default' | 'primary'; // default type, affects the background color and text color
|
||||
}
|
||||
|
||||
|
@ -21,12 +21,13 @@ interface TourPanelProps {
|
||||
current: number;
|
||||
type: TourStepProps['type'];
|
||||
indicatorsRender?: TourStepProps['indicatorsRender'];
|
||||
actionsRender?: TourStepProps['actionsRender'];
|
||||
}
|
||||
|
||||
// Due to the independent design of Panel, it will be too coupled to put in rc-tour,
|
||||
// so a set of Panel logic is implemented separately in antd.
|
||||
const TourPanel: React.FC<TourPanelProps> = (props) => {
|
||||
const { stepProps, current, type, indicatorsRender } = props;
|
||||
const { stepProps, current, type, indicatorsRender, actionsRender } = props;
|
||||
const {
|
||||
prefixCls,
|
||||
total = 1,
|
||||
@ -115,6 +116,32 @@ const TourPanel: React.FC<TourPanelProps> = (props) => {
|
||||
ghost: mergedType === 'primary',
|
||||
};
|
||||
|
||||
const defaultActionsNode = (
|
||||
<>
|
||||
{current !== 0 ? (
|
||||
<Button
|
||||
size="small"
|
||||
{...secondaryBtnProps}
|
||||
{...prevButtonProps}
|
||||
onClick={prevBtnClick}
|
||||
className={classNames(`${prefixCls}-prev-btn`, prevButtonProps?.className)}
|
||||
>
|
||||
{prevButtonProps?.children ?? contextLocaleTour?.Previous}
|
||||
</Button>
|
||||
) : null}
|
||||
<Button
|
||||
size="small"
|
||||
type={mainBtnType}
|
||||
{...nextButtonProps}
|
||||
onClick={nextBtnClick}
|
||||
className={classNames(`${prefixCls}-next-btn`, nextButtonProps?.className)}
|
||||
>
|
||||
{nextButtonProps?.children ??
|
||||
(isLastStep ? contextLocaleTour?.Finish : contextLocaleTour?.Next)}
|
||||
</Button>
|
||||
</>
|
||||
);
|
||||
|
||||
return (
|
||||
<div className={`${prefixCls}-content`}>
|
||||
<div className={`${prefixCls}-inner`}>
|
||||
@ -125,27 +152,9 @@ const TourPanel: React.FC<TourPanelProps> = (props) => {
|
||||
<div className={`${prefixCls}-footer`}>
|
||||
{total > 1 && <div className={`${prefixCls}-indicators`}>{mergedIndicatorNode}</div>}
|
||||
<div className={`${prefixCls}-buttons`}>
|
||||
{current !== 0 ? (
|
||||
<Button
|
||||
{...secondaryBtnProps}
|
||||
{...prevButtonProps}
|
||||
onClick={prevBtnClick}
|
||||
size="small"
|
||||
className={classNames(`${prefixCls}-prev-btn`, prevButtonProps?.className)}
|
||||
>
|
||||
{prevButtonProps?.children ?? contextLocaleTour?.Previous}
|
||||
</Button>
|
||||
) : null}
|
||||
<Button
|
||||
type={mainBtnType}
|
||||
{...nextButtonProps}
|
||||
onClick={nextBtnClick}
|
||||
size="small"
|
||||
className={classNames(`${prefixCls}-next-btn`, nextButtonProps?.className)}
|
||||
>
|
||||
{nextButtonProps?.children ??
|
||||
(isLastStep ? contextLocaleTour?.Finish : contextLocaleTour?.Next)}
|
||||
</Button>
|
||||
{actionsRender
|
||||
? actionsRender(defaultActionsNode, { current, total })
|
||||
: defaultActionsNode}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
Loading…
Reference in New Issue
Block a user