Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(Guide): add new component #1243

Merged
merged 15 commits into from
Mar 6, 2024
2 changes: 1 addition & 1 deletion .github/workflows/typos-config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,4 @@ ded = "ded"
Hel = "Hel"

[files]
extend-exclude = ["CHANGELOG.md"]
extend-exclude = ["CHANGELOG.md", "*.snap"]
8 changes: 8 additions & 0 deletions site/docs.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -495,6 +495,14 @@ export const docs = [
component: () => import('@/dialog/dialog.md'),
componentEn: () => import('@/dialog/dialog.en-US.md'),
},
{
title: 'Guide 引导',
titleEn: 'Guide',
name: 'guide',
path: '/mobile-vue/components/guide',
component: () => import('@/guide/guide.md'),
componentEn: () => import('@/guide/guide.en-US.md'),
},
{
title: 'Popover 弹出气泡',
titleEn: 'Popover',
Expand Down
8 changes: 5 additions & 3 deletions src/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ export type OptionData = {
} & PlainObject;

export type TreeOptionData<T = string | number> = {
children?: Array<TreeOptionData<T>>;
children?: Array<TreeOptionData<T>> | boolean;
/** option label content */
label?: string | TNode;
/** option search text */
Expand All @@ -68,6 +68,8 @@ export type HorizontalAlignEnum = 'left' | 'center' | 'right';

export type VerticalAlignEnum = 'top' | 'middle' | 'bottom';

export type LayoutEnum = 'vertical' | 'horizontal';

export type ClassName = { [className: string]: any } | ClassName[] | string;

export type CSSSelector = string;
Expand Down Expand Up @@ -119,7 +121,7 @@ export type InfinityScroll = TScroll;

export interface ScrollToElementParams {
/** 跳转元素下标 */
index: number;
index?: number;
/** 跳转元素距离顶部的距离 */
top?: number;
/** 单个元素高度非固定场景下,即 isFixedRowHeight = false。延迟设置元素位置,一般用于依赖不同高度异步渲染等场景,单位:毫秒 */
Expand All @@ -128,5 +130,5 @@ export interface ScrollToElementParams {
}

export interface ComponentScrollToElementParams extends ScrollToElementParams {
key: string | number;
key?: string | number;
}
1 change: 1 addition & 0 deletions src/components.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ export { default as Icon } from './icon';
export { default as Table } from './table';
export { SideBar, SideBarItem } from './side-bar';
export { default as TPopover } from './popover';
export { default as Guide } from './guide';

// 全局配置
export * from './config-provider';
15 changes: 15 additions & 0 deletions src/config-provider/type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,10 @@ export interface GlobalConfigProvider {
* 上传组件全局配置
*/
upload?: UploadConfig;
/**
* 引导组件全局配置
* */
guide?: GuideConfig;
}

export interface ActionSheetConfig {
Expand Down Expand Up @@ -195,3 +199,14 @@ export interface UploadConfigProgress {
*/
waitingText?: string;
}

export interface GuideConfig {
/** 语言配置, “下一步” 描述文本 */
next?: string;
/** 语言配置, “跳过” 描述文本 */
skip?: string;
/** 语言配置, “完成” 描述文本 */
finish?: string;
/** 语言配置, “返回” 描述文本 */
back?: string;
}
127 changes: 127 additions & 0 deletions src/guide/demos/base.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
<template>
<div class="guide-demo">
<t-button theme="primary" content="用户引导" @click="handleClick"></t-button>
<t-popup v-model="visible" placement="bottom" style="height: 100vh; border-radius: 0" destroy-on-close>
<template #default>
<div class="guide-container">
<div class="main-title">
<div class="title-major">用户引导标题</div>
<div class="title-sub">按钮用于开启一个闭环的操作任务,如“删除”对象、“购买”商品等。</div>
</div>
<div class="field label-field">
<t-input label="标签文字" layout="vertical" placeholder="请输入内容" />
</div>
<div class="field">
<t-input label="标签文字" layout="vertical" placeholder="请输入内容" />
</div>
<div class="action">
<t-button theme="light" variant="base" size="large">重置</t-button>
<t-button theme="primary" size="large">确定</t-button>
</div>
</div>

<t-guide
v-model="current"
:steps="steps"
@change="handleChange"
@next-step-click="handleNextStepClick"
@finish="handleFinish"
@skip="handleSkip"
@back="handleBack"
>
</t-guide>
</template>
</t-popup>
</div>
</template>

<script lang="ts" setup>
import { ref } from 'vue';

import { TdGuideProps } from '../type';

const visible = ref(false);
const current = ref(-1);

const steps: TdGuideProps['steps'] = [
{
element: () => document.querySelector('.main-title'),
title: '用户引导标题',
body: '用户引导的说明文案',
placement: 'center',
},
{
element: '.label-field',
title: '用户引导标题',
body: '用户引导的说明文案',
placement: 'bottom',
highlightPadding: 0,
},
{
element: '.action',
title: '用户引导标题',
body: '用户引导的说明文案',
placement: 'bottom-right',
},
];
const handleClick = () => {
visible.value = true;
setTimeout(() => {
current.value = 0;
}, 800);
};

const handleChange: TdGuideProps['onChange'] = (current: number, { e, total }) => {
console.log(current, e, total);
};

const handleNextStepClick: TdGuideProps['onNextStepClick'] = ({ e, next, current, total }) => {
console.log(e, next, current, total);
};

const handleFinish: TdGuideProps['onFinish'] = ({ e, current, total }) => {
visible.value = false;
console.log(e, current, total);
};

const handleSkip: TdGuideProps['onSkip'] = ({ e, current, total }) => {
visible.value = false;
console.log(e, current, total);
};
const handleBack: TdGuideProps['onBack'] = ({ e, current, total }) => {
console.log(e, current, total);
};
</script>
<style scoped>
.guide-demo {
display: flex;
justify-content: center;
}
.guide-container {
height: 100%;
width: 100%;
position: relative;
}
.main-title {
margin: 16px;
display: inline-block;
}
.title-major {
font-size: 24px;
font-weight: 600;
line-height: 36px;
}
.title-sub {
font-size: 16px;
font-weight: 400;
line-height: 24px;
margin-top: 4px;
color: rgba(0, 0, 0, 0.6);
}
.action {
margin: 16px;
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 16px;
}
</style>
133 changes: 133 additions & 0 deletions src/guide/demos/custom-popover.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
<template>
<div class="guide-demo">
<t-button theme="primary" @click="handleClick">用户引导</t-button>
<t-popup v-model="visible" placement="bottom" style="height: 100vh; border-radius: 0" destroy-on-close>
<template #default>
<div class="guide-container">
<div class="main-title">
<div class="title-major">用户引导标题</div>
<div class="title-sub">按钮用于开启一个闭环的操作任务,如“删除”对象、“购买”商品等。</div>
</div>
<div class="field label-field">
<t-input label="标签文字" layout="vertical" placeholder="请输入内容" />
</div>
<div class="field">
<t-input label="标签文字" layout="vertical" placeholder="请输入内容" />
</div>
<div class="action">
<t-button theme="light" variant="base" size="large">重置</t-button>
<t-button theme="primary" size="large">确定</t-button>
</div>
</div>

<t-guide
v-model="current"
:steps="steps"
@change="handleChange"
@next-step-click="handleNextStepClick"
@finish="handleFinish"
@skip="handleSkip"
@back="handleBack"
></t-guide>
</template>
</t-popup>
</div>
</template>

<script lang="ts" setup>
import { ref } from 'vue';

import MyPopover from './my-popover.vue';
import { TdGuideProps } from '../type';

const visible = ref(false);
const current = ref(-1);

const steps: TdGuideProps['steps'] = [
{
element: '.main-title',
title: '用户引导标题',
body: '用户引导的说明文案',
placement: 'center',
// @ts-ignore
content: MyPopover,
},
{
element: '.label-field',
title: '用户引导标题',
body: '用户引导的说明文案',
placement: 'bottom',
highlightPadding: 0,
// @ts-ignore
content: MyPopover,
},
{
element: '.action',
title: '用户引导标题',
body: '用户引导的说明文案',
placement: 'bottom-right',
// @ts-ignore
content: MyPopover,
},
];
const handleClick = () => {
visible.value = true;
setTimeout(() => {
current.value = 0;
}, 800);
};

const handleChange: TdGuideProps['onChange'] = (current: number, { e, total }) => {
console.log(current, e, total);
};

const handleNextStepClick: TdGuideProps['onNextStepClick'] = ({ e, next, current, total }) => {
console.log(e, next, current, total);
};

const handleFinish: TdGuideProps['onFinish'] = ({ e, current, total }) => {
visible.value = false;
console.log(e, current, total);
};

const handleSkip: TdGuideProps['onSkip'] = ({ e, current, total }) => {
visible.value = false;
console.log(e, current, total);
};
const handleBack: TdGuideProps['onBack'] = ({ e, current, total }) => {
console.log(e, current, total);
};
</script>
<style scoped>
.guide-demo {
display: flex;
justify-content: center;
}
.guide-container {
height: 100%;
width: 100%;
position: relative;
}
.main-title {
margin: 16px;
display: inline-block;
}
.title-major {
font-size: 24px;
font-weight: 600;
line-height: 36px;
}
.title-sub {
font-size: 16px;
font-weight: 400;
line-height: 24px;
margin-top: 4px;
color: rgba(0, 0, 0, 0.6);
}
.action {
margin: 16px;
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 16px;
}
</style>
27 changes: 27 additions & 0 deletions src/guide/demos/dialog-body.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<template>
<div class="dialog-body">
<p>用户引导的说明文案</p>
<div class="img-wrapper">
<img src="https://tdesign.gtimg.com/demo/demo-image-1.png" alt="demo" />
</div>
</div>
</template>

<script setup lang="ts"></script>

<style lang="less" scoped>
.dialog-body {
.img-wrapper {
border-radius: var(--td-radius-default);
overflow: hidden;
img {
vertical-align: bottom;
width: 100%;
}
}

p {
margin-bottom: 24px;
}
}
</style>
Loading
Loading