UNPKG

@douyinfe/semi-ui

Version:

A modern, comprehensive, flexible design system and UI library. Connect DesignOps & DevOps. Quickly build beautiful React apps. Maintained by Douyin-fe team.

553 lines (518 loc) 19.6 kB
--- localeCode: zh-CN order: 85 category: 展示类 title: UserGuide 用户引导 icon: doc-userGuide brief: 用于页面对新用户进行功能引导 --- ## 代码演示 ### 如何引入 ```jsx import import { UserGuide } from '@douyinfe/semi-ui'; ``` ### 基本用法 ```jsx live=true import React from 'react'; import { UserGuide, Button, Space, Tag, Switch } from '@douyinfe/semi-ui'; () => { const [visible, setVisible] = useState(false); const showDialog = () => { setVisible(true); }; return ( <div> <Button onClick={showDialog}>开始引导</Button> <br /> <br /> <Space> <Switch id={'basic-demo-1'} defaultChecked={true}></Switch> <Tag id={'basic-demo-2'}> Default Tag </Tag> <Button id={'basic-demo-3'}>确定</Button> </Space> <UserGuide mode="popup" mask={true} visible={visible} steps={[ { target: document.querySelector('#basic-demo-1'), title: '新手引导', description: 'Hello ByteDancer!', position: 'bottom', }, { target: document.querySelector('#basic-demo-2'), title: 'Switch', description: 'This is a Semi Switch', position: 'bottom', }, { target: document.querySelector('#basic-demo-3'), title: 'Button', description: 'This is a Semi Button', position: 'bottom', }, ]} onChange={(current) => { console.log('当前引导步骤', current); }} onNext={(current) => { console.log('下一步引导'); }} onPrev={(current) => { console.log('上一步引导'); }} onFinish={() => { setVisible(false); console.log('引导完成'); }} onSkip={() => { setVisible(false); console.log('跳过引导'); }} /> </div> ); }; ``` ### 主题 `popup` 气泡卡片模式下提供两种主题 `default` 和 `primary`,通过 `theme` 属性设置。 ```jsx live=true import React from 'react'; import { UserGuide, Button, Space, Tag, Switch } from '@douyinfe/semi-ui'; () => { const [visible, setVisible] = useState(false); const showDialog = () => { setVisible(true); }; return ( <div> <Button onClick={showDialog}>开始引导</Button> <br /> <br /> <Space> <Switch id={'theme-demo-1'} defaultChecked={true}></Switch> <Tag id={'theme-demo-2'}> Default Tag </Tag> <Button id={'theme-demo-3'}>确定</Button> </Space> <UserGuide mode="popup" mask={true} visible={visible} theme="primary" steps={[ { target: document.querySelector('#theme-demo-1'), title: '新手引导', description: 'Hello ByteDancer!', position: 'bottom', }, { target: document.querySelector('#theme-demo-2'), title: 'Switch', description: 'This is a Semi Switch', position: 'bottom', }, { target: document.querySelector('#theme-demo-3'), title: 'Button', description: 'This is a Semi Button', position: 'bottom', }, ]} onFinish={() => { setVisible(false); console.log('引导完成'); }} onSkip={() => { setVisible(false); console.log('跳过引导'); }} /> </div> ); }; ``` ### 气泡卡片弹出位置 `popup` 气泡卡片模式下提供 12 种弹出位置,可选值有`top`, `topLeft`, `topRight`, `left`, `leftTop`, `leftBottom`, `right`, `rightTop`, `rightBottom`, `bottom`, `bottomLeft`, `bottomRight`,还可以通过 `showArrow` 属性设置是否显示箭头。 ```jsx live=true import React from 'react'; import { UserGuide, Button, Space, Tag, Switch } from '@douyinfe/semi-ui'; () => { const [visible, setVisible] = useState(false); const showDialog = () => { setVisible(true); }; return ( <div> <Button id={'position-demo'} onClick={showDialog}>开始引导</Button> <UserGuide mode="popup" mask={true} visible={visible} steps={[ { target: document.querySelector('#position-demo'), title: '新手引导', description: 'Hello ByteDancer!', position: 'top', }, { target: document.querySelector('#position-demo'), title: 'New Position', description: 'This is Right Position', position: 'right', }, { target: document.querySelector('#position-demo'), title: 'Hide Arrow', description: 'We hide the arrow', position: 'bottom', showArrow: false, }, ]} onFinish={() => { setVisible(false); console.log('引导完成'); }} onSkip={() => { setVisible(false); console.log('跳过引导'); }} /> </div> ); }; ``` ### 设置高亮区域大小 通过 `spotlightPadding` 属性设置。 ```jsx live=true import React from 'react'; import { UserGuide, Button, Space, Tag, Switch } from '@douyinfe/semi-ui'; () => { const [visible, setVisible] = useState(false); const showDialog = () => { setVisible(true); }; return ( <div> <Button onClick={showDialog}>开始引导</Button> <br /> <br /> <Space> <Switch id={'padding-demo-1'} defaultChecked={true}></Switch> <Tag id={'padding-demo-2'}> Default Tag </Tag> <Button id={'padding-demo-3'}>确定</Button> </Space> <UserGuide mode="popup" mask={true} visible={visible} spotlightPadding={10} steps={[ { target: document.querySelector('#padding-demo-1'), title: '新手引导', description: 'Hello ByteDancer!', }, { target: document.querySelector('#padding-demo-2'), title: 'New Padding', description: 'This is 10px padding', }, { target: document.querySelector('#padding-demo-3'), title: 'Change Padding', spotlightPadding: 15, description: 'We change the Padding to 15px', }, ]} onFinish={() => { setVisible(false); console.log('引导完成'); }} onSkip={() => { setVisible(false); console.log('跳过引导'); }} /> </div> ); }; ``` ### 定制按钮 通过 `nextButtonProps` 和 `prevButtonProps` 属性设置按钮的样式。 ```jsx live=true import React from 'react'; import { UserGuide, Button, Space, Tag, Switch } from '@douyinfe/semi-ui'; () => { const [visible, setVisible] = useState(false); const showDialog = () => { setVisible(true); }; return ( <div> <Button onClick={showDialog}>开始引导</Button> <br /> <br /> <Space> <Switch id={'button-demo-1'} defaultChecked={true}></Switch> <Tag id={'button-demo-2'}> Default Tag </Tag> <Button id={'button-demo-3'}>确定</Button> </Space> <UserGuide mode="popup" mask={true} visible={visible} nextButtonProps={{ children: 'Next', }} prevButtonProps={{ children: 'Prev', theme: 'borderless', }} finishText="我知道啦!" steps={[ { target: document.querySelector('#button-demo-1'), title: '新手引导', description: 'Hello ByteDancer!', }, { target: document.querySelector('#button-demo-2'), title: 'New Button Style', description: 'Button text is Next', }, { target: document.querySelector('#button-demo-3'), title: 'New finish button text', description: 'Button text is I know', }, ]} onFinish={() => { setVisible(false); console.log('引导完成'); }} onSkip={() => { setVisible(false); console.log('跳过引导'); }} /> </div> ); }; ``` ### 受控 通过 `current` 属性设置当前引导步骤。 ```jsx live=true import React from 'react'; import { UserGuide, Button, Space, Tag, Switch } from '@douyinfe/semi-ui'; () => { const [visible, setVisible] = useState(false); const [current, setCurrent] = useState(0); const showDialog = () => { setVisible(true); }; return ( <div> <Button onClick={showDialog}>开始引导</Button> <br /> <br /> <Space> <Switch id={'controlled-demo-1'} defaultChecked={true}></Switch> <Tag id={'controlled-demo-2'}> Default Tag </Tag> <Button id={'controlled-demo-3'}>确定</Button> </Space> <UserGuide mode="popup" mask={true} visible={visible} current={current} steps={[ { target: document.querySelector('#controlled-demo-1'), title: '新手引导', description: 'Hello ByteDancer!', position: 'bottom', }, { target: document.querySelector('#controlled-demo-2'), title: 'Switch', description: 'This is a Semi Switch', position: 'bottom', }, { target: document.querySelector('#controlled-demo-3'), title: 'Button', description: 'This is a Semi Button', position: 'bottom', }, ]} onChange={(current) => { setCurrent(current); }} onFinish={() => { setVisible(false); setCurrent(0); console.log('引导完成'); }} onSkip={() => { setVisible(false); setCurrent(0); console.log('跳过引导'); }} /> </div> ); }; ``` ### 弹窗式引导 通过 `mode` 属性设置为 `modal` 开启弹窗式引导。 ```jsx live=true import React from 'react'; import { UserGuide, Button, Space, Tag, Switch, Image, Typography } from '@douyinfe/semi-ui'; () => { const [visible, setVisible] = useState(false); const showDialog = () => { setVisible(true); }; return ( <div> <Button onClick={showDialog}>开始引导</Button> <UserGuide mode="modal" mask={true} visible={visible} steps={[ { title: '欢迎使用 Semi DSM!', description: <div>你可以从已发布的主题出发,或者选择{<Typography.Text strong>立即创造</Typography.Text>}来创造一个新的主题</div>, cover: <Image width={'600px'} height={'100%'} src="https://lf9-static.bytednsdoc.com/obj/eden-cn/nuhpxphk/dsm/dsm_welcome.png" />, position: 'bottom', }, { title: '高可用的色盘', description: '选取主色后,我们的颜色算法会为你生成一套高可用的色盘', cover: <Image width={'600px'} height={'100%'} src="https://lf9-static.bytednsdoc.com/obj/eden-cn/nuhpxphk/dsm/dsm_console.png" />, position: 'bottom', }, { title: '自由定制', description: '开始定制属于你的设计系统吧!', cover: <Image width={'600px'} height={'100%'} src="https://lf9-static.bytednsdoc.com/obj/eden-cn/nuhpxphk/dsm/dsm_palette.png" />, position: 'bottom', }, ]} onChange={(current) => { console.log('当前引导步骤', current); }} onNext={(current) => { console.log('下一步引导'); }} onPrev={(current) => { console.log('上一步引导'); }} onFinish={() => { setVisible(false); console.log('引导完成'); }} onSkip={() => { setVisible(false); console.log('跳过引导'); }} /> </div> ); }; ``` ### 无遮罩 通过 `mask` 属性设置为 `false` 开启无遮罩引导。 ```jsx live=true import React from 'react'; import { UserGuide, Button, Space, Tag, Switch, Image } from '@douyinfe/semi-ui'; () => { const [visible, setVisible] = useState(false); const showDialog = () => { setVisible(true); }; return ( <div> <Button id={'mask-demo'} onClick={showDialog}>开始引导</Button> <UserGuide mode="popup" mask={false} visible={visible} steps={[ { target: document.querySelector('#mask-demo'), title: 'No Mask', description: 'Hello ByteDancer!', }, ]} onFinish={() => { setVisible(false); console.log('引导完成'); }} onSkip={() => { setVisible(false); console.log('跳过引导'); }} /> </div> ); }; ``` ## API 参考 --- | 属性 | 说明 | 类型 | 默认值 | 版本 | | --- | --- | --- | --- | --- | | className | 自定义类名 | string | - | | | current | 当前步骤的索引 | number | 0 | | | finishText | 最后一步完成按钮的文本 | string | '完成' | | | mask | 是否显示蒙层 | boolean | true | | | mode | 引导模式,可选值:`popup`(气泡卡片)或 `modal`(弹窗式) | string | popup | | | nextButtonProps | 下一步按钮的属性 | ButtonProps | {} | | | onChange | 步骤改变时的回调 | function(current: number) | () => void | | | onFinish | 完成所有步骤时的回调 | function() | () => void | | | onNext | 点击下一步按钮时的回调 | function(current: number) | () => void | | | onPrev | 点击上一步按钮时的回调 | function(current: number) | () => void | | | onSkip | 点击跳过按钮时的回调 | function() | () => void | | | position | 弹出层相对于目标元素的位置,可选值:`top`, `topLeft`, `topRight`, `left`, `leftTop`, `leftBottom`, `right`, `rightTop`, `rightBottom`, `bottom`, `bottomLeft`, `bottomRight` | string | bottom | | | prevButtonProps | 上一步按钮的属性 | ButtonProps | {} | | | showPrevButton | 是否显示上一步按钮 | boolean | true | | | showSkipButton | 是否显示跳过按钮 | boolean | true | | | spotlightPadding | 高亮区域的内边距,单位为像素 | number | - | | | steps | 引导步骤配置,必填 | StepItem[] | [] | | | style | 自定义样式 | React.CSSProperties | - | | | theme | 主题样式,可选值:`default` 或 `primary` | string | default | | | visible | 是否显示引导 | boolean | false | | | getPopupContainer | 指定父级 DOM,弹层将会渲染至该 DOM 中 | () => HTMLElement | - | | | zIndex | 弹层层级 | number | 1030 | | ### Steps.Step | 属性 | 说明 | 类型 | 默认值 | 版本 | | --- | --- | --- | --- | --- | | className | 步骤的自定义类名 | string | - | | | cover | 步骤的封面图 | ReactNode | - | | | target | 目标元素,高亮区域会聚焦到这个元素上 | (() => Element) \| Element | - | | | title | 步骤标题 | string \| ReactNode | - | | | description | 步骤描述 | ReactNode | - | | | mask | 是否显示此步骤的蒙层,会覆盖全局配置 | boolean | - | | | showArrow | 是否显示箭头(仅在 mode=`popup` 时有效) | boolean | true | | | spotlightPadding | 此步骤高亮区域区域的内边距,会覆盖全局配置 | number | - | | | theme | 此步骤的主题,会覆盖全局配置 | `default` \| `primary` | - | | | position | 此步骤弹出层的位置,会覆盖全局配置 | Position | - | | ## 设计变量 <DesignToken/>