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
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;
}
126 changes: 126 additions & 0 deletions src/guide/demos/base.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
<template>
<div class="guide-demo">
<t-button theme="primary" content="Button" @click="handleClick"></t-button>
<t-popup v-model="visible" placement="bottom" style="height: 100vh" destroy-on-close>
<template #default>
<div class="guide-container">
<div class="main-title">
<div class="title-major">User guide title</div>
<div class="title-sub">User guide description copy.</div>
</div>
<div class="field label-field">
<t-input label="Label" layout="vertical" placeholder="placeholder" />
</div>
<div class="field">
<t-input label="Label" layout="vertical" placeholder="placeholder" />
</div>
<div class="action">
<t-button theme="light" variant="base" size="large">Reset</t-button>
<t-button theme="primary" size="large">Confirm</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: 'User guide title',
body: 'User guide description copy.',
placement: 'center',
},
{
element: '.label-field',
title: 'User guide title',
body: 'User guide description copy.',
placement: 'bottom',
highlightPadding: 0,
},
{
element: '.action',
title: 'User guide title',
body: 'User guide description copy.',
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;
color: rgba(0, 0, 0, 0.6);
}
.action {
margin: 16px;
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 16px;
}
</style>
132 changes: 132 additions & 0 deletions src/guide/demos/custom-popover.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
<template>
<div class="guide-demo">
<t-button theme="primary" @click="handleClick">Button</t-button>
<t-popup v-model="visible" placement="bottom" style="height: 100vh" destroy-on-close>
<template #default>
<div class="guide-container">
<div class="main-title">
<div class="title-major">User guide title</div>
<div class="title-sub">User guide description copy.</div>
</div>
<div class="field label-field">
<t-input label="Label" layout="vertical" placeholder="placeholder" />
</div>
<div class="field">
<t-input label="Label" layout="vertical" placeholder="placeholder" />
</div>
<div class="action">
<t-button theme="light" variant="base" size="large">Reset</t-button>
<t-button theme="primary" size="large">Confirm</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: 'User guide title',
body: 'User guide description copy.',
placement: 'center',
// @ts-ignore
content: MyPopover,
},
{
element: '.label-field',
title: 'User guide title',
body: 'User guide description copy.',
placement: 'bottom',
highlightPadding: 0,
// @ts-ignore
content: MyPopover,
},
{
element: '.action',
title: 'User guide title',
body: 'User guide description copy.',
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;
color: rgba(0, 0, 0, 0.6);
}
.action {
margin: 16px;
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 16px;
}
</style>
31 changes: 31 additions & 0 deletions src/guide/demos/dialog-body.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<template>
<div class="dialog-body">
<p>User guide description copy.</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;
color: var(--td-text-color-secondary);
font-size: 14px;
font-weight: 400;
line-height: 22px;
}
}
</style>
Loading
Loading