feat: Steps component

This commit is contained in:
chenjiahan
2020-07-06 16:59:44 +08:00
parent e8d190d51d
commit 4500e71f1a
12 changed files with 781 additions and 8 deletions
+89
View File
@@ -0,0 +1,89 @@
# Steps
### Install
```js
import Vue from 'vue';
import { Step, Steps } from 'vant';
Vue.use(Step);
Vue.use(Steps);
```
## Usage
### Basic Usage
```html
<van-steps :active="active">
<van-step>Step1</van-step>
<van-step>Step2</van-step>
<van-step>Step3</van-step>
<van-step>Step4</van-step>
</van-steps>
```
```js
export default {
data() {
return {
active: 1,
};
},
};
```
### Custom Style
```html
<van-steps :active="active" active-icon="success" active-color="#38f">
<van-step>Step1</van-step>
<van-step>Step2</van-step>
<van-step>Step3</van-step>
<van-step>Step4</van-step>
</van-steps>
```
### Vertical Steps
```html
<van-steps direction="vertical" :active="0">
<van-step>
<h3>【City】Status1</h3>
<p>2016-07-12 12:40</p>
</van-step>
<van-step>
<h3>【City】Status2</h3>
<p>2016-07-11 10:00</p>
</van-step>
<van-step>
<h3>【City】Status3</h3>
<p>2016-07-10 09:30</p>
</van-step>
</van-steps>
```
## API
### Steps Props
| Attribute | Description | Type | Default |
| ------------- | ------------------------ | ------------------ | ------------ |
| active | Active step | _number \| string_ | `0` |
| direction | Can be set to `vertical` | _string_ | `horizontal` |
| active-color | Active step color | _string_ | `#07c160` |
| active-icon | Active icon name | _string_ | `checked` |
| inactive-icon | Active icon name | _string_ | - |
### Step Slots
| Name | Description |
| ------------- | -------------------- |
| active-icon | Custom active icon |
| inactive-icon | Custom inactive icon |
### Steps Events
| Event | Description | Arguments |
| --- | --- | --- |
| click-step `v2.5.9` | Triggered when a step's title or icon is clicked | _index: number_ |
+95
View File
@@ -0,0 +1,95 @@
# Steps 步骤条
### 引入
```js
import Vue from 'vue';
import { Step, Steps } from 'vant';
Vue.use(Step);
Vue.use(Steps);
```
## 代码演示
### 基础用法
`active`属性表示当前步骤的索引,从 0 起计
```html
<van-steps :active="active">
<van-step>买家下单</van-step>
<van-step>商家接单</van-step>
<van-step>买家提货</van-step>
<van-step>交易完成</van-step>
</van-steps>
```
```js
export default {
data() {
return {
active: 1,
};
},
};
```
### 自定义样式
可以通过`active-icon``active-color`属性设置激活状态下的图标和颜色
```html
<van-steps :active="active" active-icon="success" active-color="#38f">
<van-step>买家下单</van-step>
<van-step>商家接单</van-step>
<van-step>买家提货</van-step>
<van-step>交易完成</van-step>
</van-steps>
```
### 竖向步骤条
可以通过设置`direction`属性来改变步骤条的显示方向
```html
<van-steps direction="vertical" :active="0">
<van-step>
<h3>【城市】物流状态1</h3>
<p>2016-07-12 12:40</p>
</van-step>
<van-step>
<h3>【城市】物流状态2</h3>
<p>2016-07-11 10:00</p>
</van-step>
<van-step>
<h3>快件已发货</h3>
<p>2016-07-10 09:30</p>
</van-step>
</van-steps>
```
## API
### Steps Props
| 参数 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
| active | 当前步骤 | _number \| string_ | `0` |
| direction | 显示方向,可选值为 `vertical` | _string_ | `horizontal` |
| active-color | 激活状态颜色 | _string_ | `#07c160` |
| active-icon | 激活状态底部图标,可选值见 [Icon 组件](#/zh-CN/icon) | _string_ | `checked` |
| inactive-icon | 未激活状态底部图标,可选值见 [Icon 组件](#/zh-CN/icon) | _string_ | - |
### Step Slots
| 名称 | 说明 |
| ------------- | -------------------- |
| active-icon | 自定义激活状态图标 |
| inactive-icon | 自定义未激活状态图标 |
### Steps Events
| 事件名 | 说明 | 回调参数 |
| ------------------- | -------------------------- | --------------- |
| click-step `v2.5.9` | 点击步骤的标题或图标时触发 | _index: number_ |
+116
View File
@@ -0,0 +1,116 @@
<template>
<demo-section>
<demo-block :title="t('basicUsage')">
<van-steps :active="active">
<van-step>{{ t('step1') }}</van-step>
<van-step>{{ t('step2') }}</van-step>
<van-step>{{ t('step3') }}</van-step>
<van-step>{{ t('step4') }}</van-step>
</van-steps>
<van-button @click="nextStep">{{ t('nextStep') }}</van-button>
</demo-block>
<demo-block :title="t('customStyle')">
<van-steps
:active="active"
active-icon="success"
inactive-icon="arrow"
active-color="#38f"
>
<van-step>{{ t('step1') }}</van-step>
<van-step>{{ t('step2') }}</van-step>
<van-step>{{ t('step3') }}</van-step>
<van-step>{{ t('step4') }}</van-step>
</van-steps>
</demo-block>
<demo-block :title="t('title3')">
<van-steps :active="0" direction="vertical">
<van-step>
<h3>{{ t('status1') }}</h3>
<p>2016-07-12 12:40</p>
</van-step>
<van-step>
<h3>{{ t('status2') }}</h3>
<p>2016-07-11 10:00</p>
</van-step>
<van-step>
<h3>{{ t('status3') }}</h3>
<p>2016-07-10 09:30</p>
</van-step>
</van-steps>
</demo-block>
</demo-section>
</template>
<script>
export default {
i18n: {
'zh-CN': {
nextStep: '下一步',
step1: '买家下单',
step2: '商家接单',
step3: '买家提货',
step4: '交易完成',
title2: '描述信息',
title3: '竖向步骤条',
status1: '【城市】物流状态1',
status2: '【城市】物流状态',
status3: '快件已发货',
customStyle: '自定义样式',
},
'en-US': {
nextStep: 'Next Step',
step1: 'Step1',
step2: 'Step2',
step3: 'Step3',
step4: 'Step4',
title2: 'Description',
title3: 'Vertical Steps',
status1: '【City】Status1',
status2: '【City】Status2',
status3: '【City】Status3',
customStyle: 'Custom Style',
},
},
data() {
return {
active: 1,
};
},
methods: {
nextStep() {
this.active = ++this.active % 4;
},
},
};
</script>
<style lang="less">
@import '../../style/var';
.demo-steps {
.steps-success,
.van-icon-location {
color: @green;
}
.van-button {
margin: @padding-md 0 0 @padding-md;
}
p,
h3 {
margin: 0;
font-weight: normal;
font-size: inherit;
}
.van-steps__message + p {
margin-bottom: 10px;
}
}
</style>
+35
View File
@@ -0,0 +1,35 @@
import { createNamespace } from '../utils';
import { ParentMixin } from '../mixins/relation';
const [createComponent, bem] = createNamespace('steps');
export default createComponent({
mixins: [ParentMixin('vanSteps')],
props: {
activeColor: String,
inactiveIcon: String,
active: {
type: [Number, String],
default: 0,
},
direction: {
type: String,
default: 'horizontal',
},
activeIcon: {
type: String,
default: 'checked',
},
},
emits: ['click-step'],
render() {
return (
<div class={bem([this.direction])}>
<div class={bem('items')}>{this.$slots.default?.()}</div>
</div>
);
},
});
+21
View File
@@ -0,0 +1,21 @@
@import '../style/var';
.van-steps {
overflow: hidden;
background-color: @steps-background-color;
&--horizontal {
padding: 10px 10px 0;
.van-steps__items {
position: relative;
display: flex;
margin: 0 0 10px;
padding-bottom: 22px;
}
}
&--vertical {
padding: 0 0 0 @padding-xl;
}
}
@@ -0,0 +1,96 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`renders demo correctly 1`] = `
<div>
<div>
<div class="van-steps van-steps--horizontal">
<div class="van-steps__items">
<div class="van-hairline van-step van-step--horizontal van-step--finish">
<div class="van-step__title">买家下单</div>
<div class="van-step__circle-container"><i class="van-step__circle"></i></div>
<div class="van-step__line"></div>
</div>
<div class="van-hairline van-step van-step--horizontal van-step--process">
<div class="van-step__title van-step__title--active">商家接单</div>
<div class="van-step__circle-container"><i class="van-icon van-icon-checked van-step__icon van-step__icon--active">
<!----></i></div>
<div class="van-step__line"></div>
</div>
<div class="van-hairline van-step van-step--horizontal">
<div class="van-step__title">买家提货</div>
<div class="van-step__circle-container"><i class="van-step__circle"></i></div>
<div class="van-step__line"></div>
</div>
<div class="van-hairline van-step van-step--horizontal">
<div class="van-step__title">交易完成</div>
<div class="van-step__circle-container"><i class="van-step__circle"></i></div>
<div class="van-step__line"></div>
</div>
</div>
</div> <button class="van-button van-button--default van-button--normal">
<div class="van-button__content"><span class="van-button__text">下一步</span></div>
</button>
</div>
<div>
<div class="van-steps van-steps--horizontal">
<div class="van-steps__items">
<div class="van-hairline van-step van-step--horizontal van-step--finish">
<div class="van-step__title">买家下单</div>
<div class="van-step__circle-container"><i class="van-icon van-icon-arrow van-step__icon">
<!----></i></div>
<div class="van-step__line" style="background: rgb(51, 136, 255);"></div>
</div>
<div class="van-hairline van-step van-step--horizontal van-step--process">
<div class="van-step__title van-step__title--active" style="color: rgb(51, 136, 255);">商家接单</div>
<div class="van-step__circle-container"><i class="van-icon van-icon-success van-step__icon van-step__icon--active" style="color: rgb(51, 136, 255);">
<!----></i></div>
<div class="van-step__line"></div>
</div>
<div class="van-hairline van-step van-step--horizontal">
<div class="van-step__title">买家提货</div>
<div class="van-step__circle-container"><i class="van-icon van-icon-arrow van-step__icon">
<!----></i></div>
<div class="van-step__line"></div>
</div>
<div class="van-hairline van-step van-step--horizontal">
<div class="van-step__title">交易完成</div>
<div class="van-step__circle-container"><i class="van-icon van-icon-arrow van-step__icon">
<!----></i></div>
<div class="van-step__line"></div>
</div>
</div>
</div>
</div>
<div>
<div class="van-steps van-steps--vertical">
<div class="van-steps__items">
<div class="van-hairline van-step van-step--vertical van-step--process">
<div class="van-step__title van-step__title--active">
<h3>【城市】物流状态1</h3>
<p>2016-07-12 12:40</p>
</div>
<div class="van-step__circle-container"><i class="van-icon van-icon-checked van-step__icon van-step__icon--active">
<!----></i></div>
<div class="van-step__line"></div>
</div>
<div class="van-hairline van-step van-step--vertical">
<div class="van-step__title">
<h3>【城市】物流状态</h3>
<p>2016-07-11 10:00</p>
</div>
<div class="van-step__circle-container"><i class="van-step__circle"></i></div>
<div class="van-step__line"></div>
</div>
<div class="van-hairline van-step van-step--vertical">
<div class="van-step__title">
<h3>快件已发货</h3>
<p>2016-07-10 09:30</p>
</div>
<div class="van-step__circle-container"><i class="van-step__circle"></i></div>
<div class="van-step__line"></div>
</div>
</div>
</div>
</div>
</div>
`;
@@ -0,0 +1,29 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`icon slot 1`] = `
<div class="van-steps van-steps--horizontal">
<div class="van-steps__items">
<div class="van-hairline van-step van-step--horizontal van-step--finish">
<div class="van-step__title">
A
</div>
<div class="van-step__circle-container">Custim Inactive Icon</div>
<div class="van-step__line"></div>
</div>
<div class="van-hairline van-step van-step--horizontal van-step--process">
<div class="van-step__title van-step__title--active">
B
</div>
<div class="van-step__circle-container">Custim Active Icon</div>
<div class="van-step__line"></div>
</div>
<div class="van-hairline van-step van-step--horizontal">
<div class="van-step__title">
C
</div>
<div class="van-step__circle-container">Custim Inactive Icon</div>
<div class="van-step__line"></div>
</div>
</div>
</div>
`;
+4
View File
@@ -0,0 +1,4 @@
import Demo from '../demo';
import { snapshotDemo } from '../../../test/demo';
snapshotDemo(Demo);
+49
View File
@@ -0,0 +1,49 @@
import { mount } from '../../../test';
test('icon slot', () => {
const wrapper = mount({
template: `
<van-steps :active="1">
<van-step>
<template v-slot:inactive-icon>Custim Inactive Icon</template>
A
</van-step>
<van-step>
<template v-slot:active-icon>Custim Active Icon</template>
B
</van-step>
<van-step>
<template v-slot:inactive-icon>Custim Inactive Icon</template>
C
</van-step>
</van-steps>
`,
});
expect(wrapper).toMatchSnapshot();
});
test('click-step event', () => {
const onClickStep = jest.fn();
const wrapper = mount({
template: `
<van-steps :active="1" @click-step="onClickStep">
<van-step>A</van-step>
<van-step>B</van-step>
<van-step>C</van-step>
</van-steps>
`,
methods: {
onClickStep,
},
});
wrapper.find('.van-step').trigger('click');
expect(onClickStep).toHaveBeenCalledTimes(0);
wrapper.find('.van-step__title').trigger('click');
expect(onClickStep).toHaveBeenCalledWith(0);
wrapper.findAll('.van-step__circle-container').at(2).trigger('click');
expect(onClickStep).toHaveBeenCalledTimes(2);
expect(onClickStep).toHaveBeenLastCalledWith(2);
});