Timeline: add timeline component (#14248)

* Table: fix params order of row events (#12086)

* Timeline: add timeline component (#11736)

* Timeline: add timeline component

* Timeline: add timeline component

* Timeline: add test case

* Timeline: fix icon class

* Timeline: update docs

* Timeline: fix test case

* Timeline: remove pending attribute

* Timeline: fix docs

* Timeline: make reverse default to false

* Timline: fix test case

* Timeline: update element-ui.d.ts

* Timeline: optimize code
pull/14297/head
Zhi Cun 2019-02-01 17:13:08 +08:00 committed by GitHub
parent b350749d42
commit f17533ab11
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 1126 additions and 12 deletions

View File

@ -67,5 +67,7 @@
"header": "./packages/header/index.js", "header": "./packages/header/index.js",
"aside": "./packages/aside/index.js", "aside": "./packages/aside/index.js",
"main": "./packages/main/index.js", "main": "./packages/main/index.js",
"footer": "./packages/footer/index.js" "footer": "./packages/footer/index.js",
"timeline": "./packages/timeline/index.js",
"timeline-item": "./packages/timeline-item/index.js"
} }

View File

@ -2097,9 +2097,9 @@ You can customize row index in `type=index` columns.
| cell-mouse-leave | triggers when hovering out of a cell | row, column, cell, event | | cell-mouse-leave | triggers when hovering out of a cell | row, column, cell, event |
| cell-click | triggers when clicking a cell | row, column, cell, event | | cell-click | triggers when clicking a cell | row, column, cell, event |
| cell-dblclick | triggers when double clicking a cell | row, column, cell, event | | cell-dblclick | triggers when double clicking a cell | row, column, cell, event |
| row-click | triggers when clicking a row | row, event, column | | row-click | triggers when clicking a row | row, column, event |
| row-contextmenu | triggers when user right clicks on a row | row, event | | row-contextmenu | triggers when user right clicks on a row | row, column, event |
| row-dblclick | triggers when double clicking a row | row, event | | row-dblclick | triggers when double clicking a row | row, column, event |
| header-click | triggers when clicking a column header | column, event | | header-click | triggers when clicking a column header | column, event |
| header-contextmenu | triggers when user right clicks on a column header | column, event | | header-contextmenu | triggers when user right clicks on a column header | column, event |
| sort-change | triggers when Table's sorting changes | { column, prop, order } | | sort-change | triggers when Table's sorting changes | { column, prop, order } |

View File

@ -0,0 +1,199 @@
<script>
export default {
data() {
return {
reverse: true,
activities: [{
content: 'Event start',
timestamp: '2018-04-15'
}, {
content: 'Approved',
timestamp: '2018-04-13'
}, {
content: 'Success',
timestamp: '2018-04-11'
}],
activities2: [{
content: 'Custom icon',
timestamp: '2018-04-12 20:46',
size: 'large',
type: 'primary',
icon: 'el-icon-more'
}, {
content: 'Custom color',
timestamp: '2018-04-03 20:46',
color: '#0bbd87'
}, {
content: 'Custom size',
timestamp: '2018-04-03 20:46',
size: 'large'
}, {
content: 'Default node',
timestamp: '2018-04-03 20:46'
}]
};
}
};
</script>
<style>
.demo-timeline .source .radio {
margin-bottom: 20px;
}
.demo-timeline .source .radio .el-radio-group {
margin-left: 20px;
}
</style>
## Timeline
Visually display timeline.
### Basic usage
Timeline can be split into multiple activities in ascending or descending. Timestamps are important features that distinguish them from other components. Note the difference with Steps.
:::demo
```html
<div class="block">
<div class="radio">
Order:
<el-radio-group v-model="reverse">
<el-radio :label="true">descending</el-radio>
<el-radio :label="false">ascending</el-radio>
</el-radio-group>
</div>
<el-timeline :reverse="reverse">
<el-timeline-item
v-for="(activity, index) in activities"
:key="index"
:timestamp="activity.timestamp">
{{activity.content}}
</el-timeline-item>
</el-timeline>
</div>
<script>
export default {
data() {
return {
reverse: true,
activities: [{
content: 'Event start',
timestamp: '2018-04-15'
}, {
content: 'Approved',
timestamp: '2018-04-13'
}, {
content: 'Success',
timestamp: '2018-04-11'
}]
};
}
};
</script>
```
:::
### Custom node
Size, color, and icons can be customized in node.
:::demo
```html
<div class="block">
<el-timeline>
<el-timeline-item
v-for="(activity, index) in activities2"
:key="index"
:icon="activity.icon"
:type="activity.type"
:color="activity.color"
:size="activity.size"
:timestamp="activity.timestamp">
{{activity.content}}
</el-timeline-item>
</el-timeline>
</div>
<script>
export default {
data() {
return {
activities2: [{
content: 'Custom icon',
timestamp: '2018-04-12 20:46',
size: 'large',
type: 'primary',
icon: 'el-icon-more'
}, {
content: 'Custom color',
timestamp: '2018-04-03 20:46',
color: '#0bbd87'
}, {
content: 'Custom size',
timestamp: '2018-04-03 20:46',
size: 'large'
}, {
content: 'Default node',
timestamp: '2018-04-03 20:46'
}]
};
}
};
</script>
```
:::
### Custom timestamp
Timestamp can be placed on top of content when content is too high.
:::demo
```html
<div class="block">
<el-timeline>
<el-timeline-item timestamp="2018/4/12" placement="top">
<el-card>
<h4>Update Github template</h4>
<p>Tom committed 2018/4/12 20:46</p>
</el-card>
</el-timeline-item>
<el-timeline-item timestamp="2018/4/3" placement="top">
<el-card>
<h4>Update Github template</h4>
<p>Tom committed 2018/4/3 20:46</p>
</el-card>
</el-timeline-item>
<el-timeline-item timestamp="2018/4/2" placement="top">
<el-card>
<h4>Update Github template</h4>
<p>Tom committed 2018/4/2 20:46</p>
</el-card>
</el-timeline-item>
</el-timeline>
</div>
```
:::
### Timeline Attributes
| Attribute | Description | Type | Accepted Values | Default |
|---------- |-------- |---------- |------------- |-------- |
| reverse | whether the node is ascending or descending, default is ascending | boolean | — | false |
### Timeline-item Attributes
| Attribute | Description | Type | Accepted Values | Default |
|---------- |-------- |---------- |------------- |-------- |
| timestamp | timestamp content | string | - | — |
| hide-timestamp | whether to show timestamp | boolean | — | false |
| placement | position of timestamp | string | top / bottom | bottom |
| type | node type | string | primary / success / warning / danger / info | - |
| color | background color of node | string | hsl / hsv / hex / rgb | - |
| size | node size | string | normal / large | normal |
| icon | icon class name | string | — | - |
### Timeline-Item Slot
| name | Description |
|------|--------|
| — | Custom content for timeline item |
| dot | Custom defined node |

View File

@ -2099,9 +2099,9 @@ Puede personalizar el índice de la fila con la propiedad `type=index` de las co
| cell-mouse-leave | se dispara cuando se desplaza fuera de una celda | row, column, cell, event | | cell-mouse-leave | se dispara cuando se desplaza fuera de una celda | row, column, cell, event |
| cell-click | se dispara cuando se hace clic en una celda | row, column, cell, event | | cell-click | se dispara cuando se hace clic en una celda | row, column, cell, event |
| cell-dblclick | se dispara cuando se hace doble clic en una celda | row, column, cell, event | | cell-dblclick | se dispara cuando se hace doble clic en una celda | row, column, cell, event |
| row-click | se dispara cuando se hace clic en una fila | row, event, column | | row-click | se dispara cuando se hace clic en una fila | row, column, event |
| row-contextmenu | se dispara cuando el usuario hace clic derecho en una fila | row, event | | row-contextmenu | se dispara cuando el usuario hace clic derecho en una fila | row, column, event |
| row-dblclick | se dispara cuando se hace doble clic en una fila | row, event | | row-dblclick | se dispara cuando se hace doble clic en una fila | row, column, event |
| header-click | se dispara cuando se hace click en una cabecera de columna | column, event | | header-click | se dispara cuando se hace click en una cabecera de columna | column, event |
| header-contextmenu | se dispara cuando el usuario hace clic derecho en una cabecera de columna | column, event | | header-contextmenu | se dispara cuando el usuario hace clic derecho en una cabecera de columna | column, event |
| sort-change | se dispara cuando el ordenamiento de la tabla cambia | { column, prop, order } | | sort-change | se dispara cuando el ordenamiento de la tabla cambia | { column, prop, order } |

View File

@ -0,0 +1,199 @@
<script>
export default {
data() {
return {
reverse: true,
activities: [{
content: 'Success',
timestamp: '2018-04-11'
}, {
content: 'Approved',
timestamp: '2018-04-13'
}, {
content: 'Event start',
timestamp: '2018-04-15'
}],
activities2: [{
content: 'Custom icon',
timestamp: '2018-04-12 20:46',
size: 'large',
type: 'primary',
icon: 'el-icon-more'
}, {
content: 'Custom color',
timestamp: '2018-04-03 20:46',
color: '#0bbd87'
}, {
content: 'Custom size',
timestamp: '2018-04-03 20:46',
size: 'large'
}, {
content: 'Default node',
timestamp: '2018-04-03 20:46'
}]
};
}
};
</script>
<style>
.demo-timeline .source .radio {
margin-bottom: 20px;
}
.demo-timeline .source .radio .el-radio-group {
margin-left: 20px;
}
</style>
## Timeline
Visually display timeline.
### Basic usage
Timeline can be split into multiple activities in ascending or descending. Timestamps are important features that distinguish them from other components. Note the difference with Steps.
:::demo
```html
<div class="block">
<div class="radio">
Order:
<el-radio-group v-model="reverse">
<el-radio :label="true">descending</el-radio>
<el-radio :label="false">ascending</el-radio>
</el-radio-group>
</div>
<el-timeline :reverse="reverse">
<el-timeline-item
v-for="(activity, index) in activities"
:key="index"
:timestamp="activity.timestamp">
{{activity.content}}
</el-timeline-item>
</el-timeline>
</div>
<script>
export default {
data() {
return {
reverse: true,
activities: [{
content: 'Success',
timestamp: '2018-04-11'
}, {
content: 'Approved',
timestamp: '2018-04-13'
}, {
content: 'Event start',
timestamp: '2018-04-15'
}]
};
}
};
</script>
```
:::
### Custom node
Size, color, and icons can be customized in node.
:::demo
```html
<div class="block">
<el-timeline>
<el-timeline-item
v-for="(activity, index) in activities2"
:key="index"
:icon="activity.icon"
:type="activity.type"
:color="activity.color"
:size="activity.size"
:timestamp="activity.timestamp">
{{activity.content}}
</el-timeline-item>
</el-timeline>
</div>
<script>
export default {
data() {
return {
activities2: [{
content: 'Custom icon',
timestamp: '2018-04-12 20:46',
size: 'large',
type: 'primary',
icon: 'el-icon-more'
}, {
content: 'Custom color',
timestamp: '2018-04-03 20:46',
color: '#0bbd87'
}, {
content: 'Custom size',
timestamp: '2018-04-03 20:46',
size: 'large'
}, {
content: 'Default node',
timestamp: '2018-04-03 20:46'
}]
};
}
};
</script>
```
:::
### Custom timestamp
Timestamp can be placed on top of content when content is too high.
:::demo
```html
<div class="block">
<el-timeline>
<el-timeline-item timestamp="2018/4/12" placement="top">
<el-card>
<h4>Update Github template</h4>
<p>Tom committed 2018/4/12 20:46</p>
</el-card>
</el-timeline-item>
<el-timeline-item timestamp="2018/4/3" placement="top">
<el-card>
<h4>Update Github template</h4>
<p>Tom committed 2018/4/3 20:46</p>
</el-card>
</el-timeline-item>
<el-timeline-item timestamp="2018/4/2" placement="top">
<el-card>
<h4>Update Github template</h4>
<p>Tom committed 2018/4/2 20:46</p>
</el-card>
</el-timeline-item>
</el-timeline>
</div>
```
:::
### Timeline Attributes
| Attribute | Description | Type | Accepted Values | Default |
|---------- |-------- |---------- |------------- |-------- |
| reverse | whether the node is ascending or descending, default is ascending | boolean | — | false |
### Timeline-item Attributes
| Attribute | Description | Type | Accepted Values | Default |
|---------- |-------- |---------- |------------- |-------- |
| timestamp | timestamp content | string | - | — |
| hide-timestamp | whether to show timestamp | boolean | — | false |
| placement | position of timestamp | string | top / bottom | bottom |
| type | node type | string | primary / success / warning / danger / info | - |
| color | background color of node | string | hsl / hsv / hex / rgb | - |
| size | node size | string | normal / large | normal |
| icon | icon class name | string | — | - |
### Timeline-Item Slot
| name | Description |
|------|--------|
| — | Custom content for timeline item |
| dot | Custom defined node |

View File

@ -2157,9 +2157,9 @@
| cell-mouse-leave | 当单元格 hover 退出时会触发该事件 | row, column, cell, event | | cell-mouse-leave | 当单元格 hover 退出时会触发该事件 | row, column, cell, event |
| cell-click | 当某个单元格被点击时会触发该事件 | row, column, cell, event | | cell-click | 当某个单元格被点击时会触发该事件 | row, column, cell, event |
| cell-dblclick | 当某个单元格被双击击时会触发该事件 | row, column, cell, event | | cell-dblclick | 当某个单元格被双击击时会触发该事件 | row, column, cell, event |
| row-click | 当某一行被点击时会触发该事件 | row, event, column | | row-click | 当某一行被点击时会触发该事件 | row, column, event |
| row-contextmenu | 当某一行被鼠标右键点击时会触发该事件 | row, event | | row-contextmenu | 当某一行被鼠标右键点击时会触发该事件 | row, column, event |
| row-dblclick | 当某一行被双击时会触发该事件 | row, event | | row-dblclick | 当某一行被双击时会触发该事件 | row, column, event |
| header-click | 当某一列的表头被点击时会触发该事件 | column, event | | header-click | 当某一列的表头被点击时会触发该事件 | column, event |
| header-contextmenu | 当某一列的表头被鼠标右键点击时触发该事件 | column, event | | header-contextmenu | 当某一列的表头被鼠标右键点击时触发该事件 | column, event |
| sort-change | 当表格的排序条件发生变化的时候会触发该事件 | { column, prop, order } | | sort-change | 当表格的排序条件发生变化的时候会触发该事件 | { column, prop, order } |

View File

@ -0,0 +1,199 @@
<script>
export default {
data() {
return {
reverse: true,
activities: [{
content: '活动按期开始',
timestamp: '2018-04-15'
}, {
content: '通过审核',
timestamp: '2018-04-13'
}, {
content: '创建成功',
timestamp: '2018-04-11'
}],
activities2: [{
content: '支持使用图标',
timestamp: '2018-04-12 20:46',
size: 'large',
type: 'primary',
icon: 'el-icon-more'
}, {
content: '支持自定义颜色',
timestamp: '2018-04-03 20:46',
color: '#0bbd87'
}, {
content: '支持自定义尺寸',
timestamp: '2018-04-03 20:46',
size: 'large'
}, {
content: '默认样式的节点',
timestamp: '2018-04-03 20:46'
}]
};
}
};
</script>
<style>
.demo-timeline .source .radio {
margin-bottom: 20px;
}
.demo-timeline .source .radio .el-radio-group {
margin-left: 20px;
}
</style>
## Timeline 时间线
可视化地呈现时间流信息。
### 基础用法
Timeline 可拆分成多个按照时间戳正序或倒序排列的 activity时间戳是其区分于其他控件的重要特征使⽤时注意与 Steps 步骤条等区分。
:::demo
```html
<div class="block">
<div class="radio">
排序:
<el-radio-group v-model="reverse">
<el-radio :label="true">倒序</el-radio>
<el-radio :label="false">正序</el-radio>
</el-radio-group>
</div>
<el-timeline :reverse="reverse">
<el-timeline-item
v-for="(activity, index) in activities"
:key="index"
:timestamp="activity.timestamp">
{{activity.content}}
</el-timeline-item>
</el-timeline>
</div>
<script>
export default {
data() {
return {
reverse: true,
activities: [{
content: '活动按期开始',
timestamp: '2018-04-15'
}, {
content: '通过审核',
timestamp: '2018-04-13'
}, {
content: '创建成功',
timestamp: '2018-04-11'
}]
};
}
};
</script>
```
:::
### ⾃定义节点样式
可根据实际场景⾃定义节点尺⼨、颜⾊,或直接使⽤图标。
:::demo
```html
<div class="block">
<el-timeline>
<el-timeline-item
v-for="(activity, index) in activities2"
:key="index"
:icon="activity.icon"
:type="activity.type"
:color="activity.color"
:size="activity.size"
:timestamp="activity.timestamp">
{{activity.content}}
</el-timeline-item>
</el-timeline>
</div>
<script>
export default {
data() {
return {
activities2: [{
content: '支持使用图标',
timestamp: '2018-04-12 20:46',
size: 'large',
type: 'primary',
icon: 'el-icon-more'
}, {
content: '支持自定义颜色',
timestamp: '2018-04-03 20:46',
color: '#0bbd87'
}, {
content: '支持自定义尺寸',
timestamp: '2018-04-03 20:46',
size: 'large'
}, {
content: '默认样式的节点',
timestamp: '2018-04-03 20:46'
}]
};
}
};
</script>
```
:::
### ⾃定义时间戳
当内容在垂直⽅向上过⾼时,可将时间戳置于内容之上。
:::demo
```html
<div class="block">
<el-timeline>
<el-timeline-item timestamp="2018/4/12" placement="top">
<el-card>
<h4>更新 Github 模板</h4>
<p>王小虎 提交于 2018/4/12 20:46</p>
</el-card>
</el-timeline-item>
<el-timeline-item timestamp="2018/4/3" placement="top">
<el-card>
<h4>更新 Github 模板</h4>
<p>王小虎 提交于 2018/4/3 20:46</p>
</el-card>
</el-timeline-item>
<el-timeline-item timestamp="2018/4/2" placement="top">
<el-card>
<h4>更新 Github 模板</h4>
<p>王小虎 提交于 2018/4/2 20:46</p>
</el-card>
</el-timeline-item>
</el-timeline>
</div>
```
:::
### Timeline Attributes
| 参数 | 说明 | 类型 | 可选值 | 默认值 |
|---------- |-------- |---------- |------------- |-------- |
| reverse | 指定节点排序方向,默认为正序 | boolean | — | false |
### Timeline-item Attributes
| 参数 | 说明 | 类型 | 可选值 | 默认值 |
|---------- |-------- |---------- |------------- |-------- |
| timestamp | 时间戳 | string | - | — |
| hide-timestamp | 是否隐藏时间戳 | boolean | — | false |
| placement | 时间戳位置 | string | top / bottom | bottom |
| type | 节点类型 | string | primary / success / warning / danger / info | - |
| color | 节点颜色 | string | hsl / hsv / hex / rgb | - |
| size | 节点尺寸 | string | normal / large | normal |
| icon | 节点图标 | string | — | - |
### Timeline-Item Slot
| name | 说明 |
|------|--------|
| — | Timeline-Item 的内容 |
| dot | 自定义节点 |

View File

@ -243,6 +243,10 @@
{ {
"path": "/collapse", "path": "/collapse",
"title": "Collapse 折叠面板" "title": "Collapse 折叠面板"
},
{
"path": "/timeline",
"title": "Timeline 时间线"
} }
] ]
} }
@ -493,6 +497,10 @@
{ {
"path": "/collapse", "path": "/collapse",
"title": "Collapse" "title": "Collapse"
},
{
"path": "/timeline",
"title": "Timeline"
} }
] ]
} }
@ -743,6 +751,10 @@
{ {
"path": "/collapse", "path": "/collapse",
"title": "Collapse" "title": "Collapse"
},
{
"path": "/timeline",
"title": "Timeline"
} }
] ]
} }

View File

@ -381,7 +381,7 @@ export default {
table.$emit(`cell-${name}`, row, column, cell, event); table.$emit(`cell-${name}`, row, column, cell, event);
} }
} }
table.$emit(`row-${name}`, row, event, column); table.$emit(`row-${name}`, row, column, event);
}, },
handleExpandClick(row, e) { handleExpandClick(row, e) {

View File

@ -683,6 +683,12 @@ $--footer-padding: 0 20px !default;
--------------------------*/ --------------------------*/
$--main-padding: 20px !default; $--main-padding: 20px !default;
/* Timeline
--------------------------*/
$--timeline-node-size-normal: 12px !default;
$--timeline-node-size-large: 14px !default;
$--timeline-node-color: $--border-color-light !default;
/* Break-point /* Break-point
--------------------------*/ --------------------------*/
$--sm: 768px !default; $--sm: 768px !default;

View File

@ -65,3 +65,5 @@
@import "./aside.scss"; @import "./aside.scss";
@import "./main.scss"; @import "./main.scss";
@import "./footer.scss"; @import "./footer.scss";
@import "./timeline.scss";
@import "./timeline-item.scss";

View File

@ -0,0 +1,86 @@
@import "mixins/mixins";
@import "common/var";
@include b(timeline-item) {
position: relative;
padding-bottom: 20px;
@include e(wrapper) {
position: relative;
padding-left: 28px;
top: -3px;
}
@include e(tail) {
position: absolute;
left: 4px;
height: 100%;
border-left: 2px solid $--timeline-node-color;
}
@include e(icon) {
color: $--color-white;
font-size: $--font-size-small;
}
@include e(node) {
position: absolute;
background-color: $--timeline-node-color;
border-radius: 50%;
display: flex;
justify-content: center;
align-items: center;
@include m(normal) {
left: -1px;
width: $--timeline-node-size-normal;
height: $--timeline-node-size-normal;
}
@include m(large) {
left: -2px;
width: $--timeline-node-size-large;
height: $--timeline-node-size-large;
}
@include m(primary) {
background-color: $--color-primary;
}
@include m(success) {
background-color: $--color-success;
}
@include m(warning) {
background-color: $--color-warning;
}
@include m(danger) {
background-color: $--color-danger;
}
@include m(info) {
background-color: $--color-info;
}
}
@include e(dot) {
position: absolute;
display: flex;
justify-content: center;
align-items: center;
}
@include e(content) {
color: $--color-text-primary;
}
@include e(timestamp) {
color: $--color-text-secondary;
line-height: 1;
font-size: $--font-size-small;
@include when(top) {
margin-bottom: 8px;
padding-top: 4px;
}
@include when(bottom) {
margin-top: 8px;
}
}
}

View File

@ -0,0 +1,14 @@
@import "mixins/mixins";
@import "common/var";
@include b(timeline) {
margin: 0;
font-size: $--font-size-base;
list-style: none;
& .el-timeline-item:last-child {
& .el-timeline-item__tail {
display: none;
}
}
}

View File

@ -0,0 +1,8 @@
import ElTimelineItem from '../timeline/src/item';
/* istanbul ignore next */
ElTimelineItem.install = function(Vue) {
Vue.component(ElTimelineItem.name, ElTimelineItem);
};
export default ElTimelineItem;

View File

@ -0,0 +1,8 @@
import Timeline from './src/main';
/* istanbul ignore next */
Timeline.install = function(Vue) {
Vue.component(Timeline.name, Timeline);
};
export default Timeline;

View File

@ -0,0 +1,73 @@
<template>
<li class="el-timeline-item">
<div class="el-timeline-item__tail"></div>
<div v-if="!$slots.dot"
class="el-timeline-item__node"
:class="[
`el-timeline-item__node--${size || ''}`,
`el-timeline-item__node--${type || ''}`
]"
:style="{
backgroundColor: color
}"
>
<i v-if="icon"
class="el-timeline-item__icon"
:class="icon"
></i>
</div>
<div v-if="$slots.dot" class="el-timeline-item__dot">
<slot name="dot"></slot>
</div>
<div class="el-timeline-item__wrapper">
<div v-if="!hideTimestamp && placement === 'top'"
class="el-timeline-item__timestamp is-top">
{{timestamp}}
</div>
<div class="el-timeline-item__content">
<slot></slot>
</div>
<div v-if="!hideTimestamp && placement === 'bottom'"
class="el-timeline-item__timestamp is-bottom">
{{timestamp}}
</div>
</div>
</li>
</template>
<script>
export default {
name: 'ElTimelineItem',
inject: ['timeline'],
props: {
timestamp: String,
hideTimestamp: {
type: Boolean,
default: false
},
placement: {
type: String,
default: 'bottom'
},
type: String,
color: String,
size: {
type: String,
default: 'normal'
},
icon: String
}
};
</script>

View File

@ -0,0 +1,38 @@
<template>
<ul class="el-timeline"
:class="{
'is-reverse': reverse
}">
<slot></slot>
</ul>
</template>
<script>
export default {
name: 'ElTimeline',
props: {
reverse: {
type: Boolean,
default: false
}
},
provide() {
return {
timeline: this
};
},
watch: {
reverse: {
handler(newVal) {
if (newVal) {
this.$slots.default = [...this.$slots.default].reverse();
}
},
immediate: true
}
}
};
</script>

View File

@ -69,6 +69,8 @@ import Header from '../packages/header/index.js';
import Aside from '../packages/aside/index.js'; import Aside from '../packages/aside/index.js';
import Main from '../packages/main/index.js'; import Main from '../packages/main/index.js';
import Footer from '../packages/footer/index.js'; import Footer from '../packages/footer/index.js';
import Timeline from '../packages/timeline/index.js';
import TimelineItem from '../packages/timeline-item/index.js';
import locale from 'element-ui/src/locale'; import locale from 'element-ui/src/locale';
import CollapseTransition from 'element-ui/src/transitions/collapse-transition'; import CollapseTransition from 'element-ui/src/transitions/collapse-transition';
@ -138,6 +140,8 @@ const components = [
Aside, Aside,
Main, Main,
Footer, Footer,
Timeline,
TimelineItem,
CollapseTransition CollapseTransition
]; ];
@ -245,5 +249,7 @@ export default {
Header, Header,
Aside, Aside,
Main, Main,
Footer Footer,
Timeline,
TimelineItem
}; };

View File

@ -0,0 +1,228 @@
import { createVue, destroyVM } from '../util';
describe('Timeline', () => {
let vm;
afterEach(() => {
destroyVM(vm);
});
it('create', () => {
vm = createVue({
template: `
<el-timeline>
<el-timeline-item
v-for="(activity, index) in activities"
:key="index"
:timestamp="activity.timestamp">
{{activity.content}}
</el-timeline-item>
</el-timeline>
`,
data() {
return {
activities: [{
content: '创建成功',
timestamp: '2018-04-11'
}, {
content: '通过审核',
timestamp: '2018-04-13'
}, {
content: '活动按期开始',
timestamp: '2018-04-15'
}]
};
}
}, true);
let contentElms = vm.$el.querySelectorAll('.el-timeline-item__content');
contentElms.forEach((elm, index) => {
expect(elm.innerText).to.equal(vm.activities[index].content);
});
let timestampElms = vm.$el.querySelectorAll('.el-timeline-item__timestamp');
timestampElms.forEach((elm, index) => {
expect(elm.innerText).to.equal(vm.activities[index].timestamp);
});
});
it('reverse', done => {
vm = createVue({
template: `
<el-timeline :reverse="reverse">
<el-timeline-item
v-for="(activity, index) in activities"
:key="index"
:timestamp="activity.timestamp">
{{activity.content}}
</el-timeline-item>
</el-timeline>
`,
data() {
return {
reverse: true,
activities: [{
content: '创建成功',
timestamp: '2018-04-11'
}, {
content: '通过审核',
timestamp: '2018-04-13'
}, {
content: '活动按期开始',
timestamp: '2018-04-15'
}]
};
}
}, true);
const contentElms = vm.$el.querySelectorAll('.el-timeline-item__content');
contentElms.forEach((elm, index) => {
expect(elm.innerText).to.equal(vm.activities[vm.activities.length - index - 1].content);
});
vm.reverse = false;
vm.$nextTick(() => {
const contentElms = vm.$el.querySelectorAll('.el-timeline-item__content');
contentElms.forEach((elm, index) => {
expect(elm.innerText).to.equal(vm.activities[index].content);
});
done();
});
});
it('placement', () => {
vm = createVue({
template: `
<el-timeline>
<el-timeline-item
v-for="(activity, index) in activities"
:key="index"
:timestamp="activity.timestamp"
:placement="activity.placement">
{{activity.content}}
</el-timeline-item>
</el-timeline>
`,
data() {
return {
activities: [{
content: '创建成功',
timestamp: '2018-04-11',
placement: 'top'
}, {
content: '通过审核',
timestamp: '2018-04-13'
}, {
content: '活动按期开始',
timestamp: '2018-04-15'
}]
};
}
}, true);
const timestampElm = vm.$el.querySelectorAll('.el-timeline-item__timestamp')[0];
expect(timestampElm.classList.contains('is-top')).to.true;
});
it('hide-timestamp', () => {
vm = createVue({
template: `
<el-timeline>
<el-timeline-item
v-for="(activity, index) in activities"
:key="index"
:timestamp="activity.timestamp"
:hide-timestamp="activity.hideTimestamp">
{{activity.content}}
</el-timeline-item>
</el-timeline>
`,
data() {
return {
activities: [{
content: '创建成功',
timestamp: '2018-04-11',
hideTimestamp: true
}, {
content: '通过审核',
timestamp: '2018-04-13'
}, {
content: '活动按期开始',
timestamp: '2018-04-15'
}]
};
}
}, true);
const timestampElms = vm.$el.querySelectorAll('.el-timeline-item__timestamp');
expect(timestampElms.length).to.equal(2);
});
it('color', () => {
vm = createVue({
template: `
<el-timeline>
<el-timeline-item
timestamp="2018-04-11"
color="#f00">
创建成功
</el-timeline-item>
</el-timeline>
`
}, true);
const nodeElm = vm.$el.querySelector('.el-timeline-item__node');
expect(nodeElm.style.backgroundColor).to.equal('rgb(255, 0, 0)');
});
it('type', () => {
vm = createVue({
template: `
<el-timeline>
<el-timeline-item
timestamp="2018-04-11"
type="primary">
创建成功
</el-timeline-item>
</el-timeline>
`
}, true);
const nodeElm = vm.$el.querySelector('.el-timeline-item__node');
expect(nodeElm.classList.contains('el-timeline-item__node--primary')).to.true;
});
it('size', () => {
vm = createVue({
template: `
<el-timeline>
<el-timeline-item
timestamp="2018-04-11"
type="large">
创建成功
</el-timeline-item>
</el-timeline>
`
}, true);
const nodeElm = vm.$el.querySelector('.el-timeline-item__node');
expect(nodeElm.classList.contains('el-timeline-item__node--large')).to.true;
});
it('icon', () => {
vm = createVue({
template: `
<el-timeline>
<el-timeline-item
timestamp="2018-04-11"
icon="el-icon-more">
创建成功
</el-timeline-item>
</el-timeline>
`
}, true);
const nodeElm = vm.$el.querySelector('.el-timeline-item__icon');
expect(nodeElm.classList.contains('el-icon-more')).to.true;
});
});

View File

@ -61,6 +61,8 @@ import { ElTableColumn } from './table-column'
import { ElTag } from './tag' import { ElTag } from './tag'
import { ElTabs } from './tabs' import { ElTabs } from './tabs'
import { ElTabPane } from './tab-pane' import { ElTabPane } from './tab-pane'
import { ElTimeline } from './timeline'
import { ElTimelineItem } from './timeline-item'
import { ElTimePicker } from './time-picker' import { ElTimePicker } from './time-picker'
import { ElTimeSelect } from './time-select' import { ElTimeSelect } from './time-select'
import { ElTooltip } from './tooltip' import { ElTooltip } from './tooltip'
@ -275,6 +277,12 @@ export class TabPane extends ElTabPane {}
/** Tag Component */ /** Tag Component */
export class Tag extends ElTag {} export class Tag extends ElTag {}
/** Timeline Component */
export class Timeline extends ElTimeline {}
/** Timeline Item Component */
export class TimelineItem extends ElTimelineItem {}
/** TimePicker Component */ /** TimePicker Component */
export class TimePicker extends ElTimePicker {} export class TimePicker extends ElTimePicker {}

20
types/timeline-item.d.ts vendored Normal file
View File

@ -0,0 +1,20 @@
import { ElementUIComponent } from './component'
export type TimelineItemPlacement = 'top' | 'bottom'
export type TimelineItemType = 'primary' | 'success' | 'warning' | 'danger' | 'info'
export type TimelineItemSize = 'normal' | 'large'
/** TimelineItem Component */
export declare class ElTimelineItem extends ElementUIComponent {
timestamp: string
hideTimestamp: boolean
placement: TimelineItemPlacement
type: TimelineItemType
size: TimelineItemSize
icon: string
}

6
types/timeline.d.ts vendored Normal file
View File

@ -0,0 +1,6 @@
import { ElementUIComponent } from './component'
/** Timeline Component */
export declare class ElTimeline extends ElementUIComponent {
reverse: boolean
}