浏览代码

Descriptions: add description component (#21129)

好多大米 4 年之前
父节点
当前提交
034da49dd9

+ 3 - 1
components.json

@@ -83,5 +83,7 @@
   "popconfirm": "./packages/popconfirm/index.js",
   "skeleton": "./packages/skeleton/index.js",
   "skeleton-item": "./packages/skeleton-item/index.js",
-  "empty": "./packages/empty/index.js"
+  "empty": "./packages/empty/index.js",
+  "descriptions": "./packages/description/index.js",
+  "descriptions-item": "./packages/description-item/index.js"
 }

+ 13 - 0
examples/demo-styles/descriptions.scss

@@ -0,0 +1,13 @@
+.demo-block.demo-descriptions {
+  .margin-top {
+    margin-top: 20px;
+  }
+
+  .my-label {
+    background: #E1F3D8;
+  }
+
+  .my-content {
+    background: #FDE2E2;
+  }
+}

+ 1 - 0
examples/demo-styles/index.scss

@@ -45,4 +45,5 @@
 @import "./avatar.scss";
 @import "./drawer.scss";
 @import "./skeleton.scss";
+@import "./descriptions.scss";
 

+ 191 - 0
examples/docs/en-US/descriptions.md

@@ -0,0 +1,191 @@
+## Descriptions
+
+Display multiple fields in list form.
+
+### Basic usage
+
+:::demo
+
+```html
+<el-descriptions title="User Info">
+    <el-descriptions-item label="Username">kooriookami</el-descriptions-item>
+    <el-descriptions-item label="Telephone">18100000000</el-descriptions-item>
+    <el-descriptions-item label="Place">Suzhou</el-descriptions-item>
+    <el-descriptions-item label="Remarks">
+      <el-tag size="small">School</el-tag>
+    </el-descriptions-item>
+    <el-descriptions-item label="Address">No.1188, Wuzhong Avenue, Wuzhong District, Suzhou, Jiangsu Province</el-descriptions-item>
+</el-descriptions>
+```
+:::
+
+### Sizes
+
+:::demo
+
+```html
+<template>
+  <el-radio-group v-model="size">
+    <el-radio label="">Default</el-radio>
+    <el-radio label="medium">Medium</el-radio>
+    <el-radio label="small">Small</el-radio>
+    <el-radio label="mini">Mini</el-radio>
+  </el-radio-group>
+
+  <el-descriptions class="margin-top" title="With border" :column="3" :size="size" border>
+    <template slot="extra">
+      <el-button type="primary" size="small">Operation</el-button>
+    </template>
+    <el-descriptions-item>
+      <template slot="label">
+        <i class="el-icon-user"></i>
+        Username
+      </template>
+      kooriookami
+    </el-descriptions-item>
+    <el-descriptions-item>
+      <template slot="label">
+        <i class="el-icon-mobile-phone"></i>
+        Telephone
+      </template>
+      18100000000
+    </el-descriptions-item>
+    <el-descriptions-item>
+      <template slot="label">
+        <i class="el-icon-location-outline"></i>
+        Place
+      </template>
+      Suzhou
+    </el-descriptions-item>
+    <el-descriptions-item>
+      <template slot="label">
+        <i class="el-icon-tickets"></i>
+        Remarks
+      </template>
+      <el-tag size="small">School</el-tag>
+    </el-descriptions-item>
+    <el-descriptions-item>
+      <template slot="label">
+        <i class="el-icon-office-building"></i>
+        Address
+      </template>
+      No.1188, Wuzhong Avenue, Wuzhong District, Suzhou, Jiangsu Province
+    </el-descriptions-item>
+  </el-descriptions>
+
+  <el-descriptions class="margin-top" title="Without border" :column="3" :size="size">
+    <template slot="extra">
+      <el-button type="primary" size="small">Operation</el-button>
+    </template>
+    <el-descriptions-item label="Username">kooriookami</el-descriptions-item>
+    <el-descriptions-item label="Telephone">18100000000</el-descriptions-item>
+    <el-descriptions-item label="Place">Suzhou</el-descriptions-item>
+    <el-descriptions-item label="Remarks">
+      <el-tag size="small">School</el-tag>
+    </el-descriptions-item>
+    <el-descriptions-item label="Address">No.1188, Wuzhong Avenue, Wuzhong District, Suzhou, Jiangsu Province</el-descriptions-item>
+  </el-descriptions>
+</template>
+
+<script>
+  export default {
+    data () {
+      return {
+        size: ''
+      };
+    }
+  }
+</script>
+```
+:::
+
+### Vertical List
+
+:::demo
+
+```html
+<el-descriptions title="Vertical list with border" direction="vertical" :column="4" border>
+  <el-descriptions-item label="Username">kooriookami</el-descriptions-item>
+  <el-descriptions-item label="Telephone">18100000000</el-descriptions-item>
+  <el-descriptions-item label="Place" :span="2">Suzhou</el-descriptions-item>
+  <el-descriptions-item label="Remarks">
+    <el-tag size="small">School</el-tag>
+  </el-descriptions-item>
+  <el-descriptions-item label="Address">No.1188, Wuzhong Avenue, Wuzhong District, Suzhou, Jiangsu Province</el-descriptions-item>
+</el-descriptions>
+
+<el-descriptions class="margin-top" title="Vertical list without border" :column="4" direction="vertical">
+  <el-descriptions-item label="Username">kooriookami</el-descriptions-item>
+  <el-descriptions-item label="Telephone">18100000000</el-descriptions-item>
+  <el-descriptions-item label="Place" :span="2">Suzhou</el-descriptions-item>
+  <el-descriptions-item label="Remarks">
+    <el-tag size="small">School</el-tag>
+  </el-descriptions-item>
+  <el-descriptions-item label="Address">No.1188, Wuzhong Avenue, Wuzhong District, Suzhou, Jiangsu Province</el-descriptions-item>
+</el-descriptions>
+```
+:::
+
+### Customized Style
+
+:::demo
+
+```html
+<el-descriptions title="Customized style list" :column="3" border>
+  <el-descriptions-item label="Username" label-class-name="my-label" content-class-name="my-content">kooriookami</el-descriptions-item>
+  <el-descriptions-item label="Telephone">18100000000</el-descriptions-item>
+  <el-descriptions-item label="Place">Suzhou</el-descriptions-item>
+  <el-descriptions-item label="Remarks">
+    <el-tag size="small">School</el-tag>
+  </el-descriptions-item>
+  <el-descriptions-item label="Address" :content-style="{'text-align': 'right'}">No.1188, Wuzhong Avenue, Wuzhong District, Suzhou, Jiangsu Province</el-descriptions-item>
+</el-descriptions>
+<style>
+  .my-label {
+    background: #E1F3D8;
+  }
+
+  .my-content {
+    background: #FDE2E2;
+  }
+</style>
+```
+:::
+
+### Descriptions Attributes
+| Attribute     | Description       | Type       | Accepted Values        | Default   |
+|-------------  |---------------- |---------------- |---------------------- |-------- |
+| border        | with or without border      | boolean  |          —             |    false     |
+| column        | numbers of `Descriptions Item` in one line  | number | — |    3  |
+| direction     | direction of list  | string | vertical / horizontal |    horizontal  |
+| size          | size of list    | string  |    medium / small / mini  |  — |
+| title         | title text, display on the top left    | string  |    —  |  — |
+| extra         | extra text, display on the top right    | string  |    —  |  — |
+| colon | change default props colon value of Descriptions Item   | boolean |    —  |  true |
+| labelClassName          | custom label class name         | string  |          —             |    —     |
+| contentClassName          | custom content class name         | string  |          —             |    —     |
+| labelStyle          | custom label style | object |          —             |    —     |
+| contentStyle         | custom content style | object |          —             |    —     |
+
+### Descriptions Slots
+
+| Name | Description |
+|------|--------|
+| title | custom title, display on the top left  |
+| extra | custom extra area, display on the top right  |
+
+### Descriptions Item Attributes
+| Attribute       | Description        | Type       | Accepted Values       | Default   |
+|-------------  |---------------- |---------------- |---------------------- |-------- |
+| label          | label text         | string  |          —             |    —     |
+| span          | colspan of column       | number  |          —             |    1     |
+| labelClassName          | custom label class name         | string  |          —             |    —     |
+| contentClassName          | custom content class name         | string  |          —             |    —     |
+| labelStyle          | custom label style | object |          —             |    —     |
+| contentStyle         | custom content style | object |          —             |    —     |
+
+### Descriptions Item Slots
+
+| Name | Description |
+|------|--------|
+| label | custom label  |

+ 191 - 0
examples/docs/es/descriptions.md

@@ -0,0 +1,191 @@
+## Descriptions
+
+Display multiple fields in list form.
+
+### Basic usage
+
+:::demo
+
+```html
+<el-descriptions title="User Info">
+    <el-descriptions-item label="Username">kooriookami</el-descriptions-item>
+    <el-descriptions-item label="Telephone">18100000000</el-descriptions-item>
+    <el-descriptions-item label="Place">Suzhou</el-descriptions-item>
+    <el-descriptions-item label="Remarks">
+      <el-tag size="small">School</el-tag>
+    </el-descriptions-item>
+    <el-descriptions-item label="Address">No.1188, Wuzhong Avenue, Wuzhong District, Suzhou, Jiangsu Province</el-descriptions-item>
+</el-descriptions>
+```
+:::
+
+### Sizes
+
+:::demo
+
+```html
+<template>
+  <el-radio-group v-model="size">
+    <el-radio label="">Default</el-radio>
+    <el-radio label="medium">Medium</el-radio>
+    <el-radio label="small">Small</el-radio>
+    <el-radio label="mini">Mini</el-radio>
+  </el-radio-group>
+
+  <el-descriptions class="margin-top" title="With border" :column="3" :size="size" border>
+    <template slot="extra">
+      <el-button type="primary" size="small">Operation</el-button>
+    </template>
+    <el-descriptions-item>
+      <template slot="label">
+        <i class="el-icon-user"></i>
+        Username
+      </template>
+      kooriookami
+    </el-descriptions-item>
+    <el-descriptions-item>
+      <template slot="label">
+        <i class="el-icon-mobile-phone"></i>
+        Telephone
+      </template>
+      18100000000
+    </el-descriptions-item>
+    <el-descriptions-item>
+      <template slot="label">
+        <i class="el-icon-location-outline"></i>
+        Place
+      </template>
+      Suzhou
+    </el-descriptions-item>
+    <el-descriptions-item>
+      <template slot="label">
+        <i class="el-icon-tickets"></i>
+        Remarks
+      </template>
+      <el-tag size="small">School</el-tag>
+    </el-descriptions-item>
+    <el-descriptions-item>
+      <template slot="label">
+        <i class="el-icon-office-building"></i>
+        Address
+      </template>
+      No.1188, Wuzhong Avenue, Wuzhong District, Suzhou, Jiangsu Province
+    </el-descriptions-item>
+  </el-descriptions>
+
+  <el-descriptions class="margin-top" title="Without border" :column="3" :size="size">
+    <template slot="extra">
+      <el-button type="primary" size="small">Operation</el-button>
+    </template>
+    <el-descriptions-item label="Username">kooriookami</el-descriptions-item>
+    <el-descriptions-item label="Telephone">18100000000</el-descriptions-item>
+    <el-descriptions-item label="Place">Suzhou</el-descriptions-item>
+    <el-descriptions-item label="Remarks">
+      <el-tag size="small">School</el-tag>
+    </el-descriptions-item>
+    <el-descriptions-item label="Address">No.1188, Wuzhong Avenue, Wuzhong District, Suzhou, Jiangsu Province</el-descriptions-item>
+  </el-descriptions>
+</template>
+
+<script>
+  export default {
+    data () {
+      return {
+        size: ''
+      };
+    }
+  }
+</script>
+```
+:::
+
+### Vertical List
+
+:::demo
+
+```html
+<el-descriptions title="Vertical list with border" direction="vertical" :column="4" border>
+  <el-descriptions-item label="Username">kooriookami</el-descriptions-item>
+  <el-descriptions-item label="Telephone">18100000000</el-descriptions-item>
+  <el-descriptions-item label="Place" :span="2">Suzhou</el-descriptions-item>
+  <el-descriptions-item label="Remarks">
+    <el-tag size="small">School</el-tag>
+  </el-descriptions-item>
+  <el-descriptions-item label="Address">No.1188, Wuzhong Avenue, Wuzhong District, Suzhou, Jiangsu Province</el-descriptions-item>
+</el-descriptions>
+
+<el-descriptions class="margin-top" title="Vertical list without border" :column="4" direction="vertical">
+  <el-descriptions-item label="Username">kooriookami</el-descriptions-item>
+  <el-descriptions-item label="Telephone">18100000000</el-descriptions-item>
+  <el-descriptions-item label="Place" :span="2">Suzhou</el-descriptions-item>
+  <el-descriptions-item label="Remarks">
+    <el-tag size="small">School</el-tag>
+  </el-descriptions-item>
+  <el-descriptions-item label="Address">No.1188, Wuzhong Avenue, Wuzhong District, Suzhou, Jiangsu Province</el-descriptions-item>
+</el-descriptions>
+```
+:::
+
+### Customized Style
+
+:::demo
+
+```html
+<el-descriptions title="Customized style list" :column="3" border>
+  <el-descriptions-item label="Username" label-class-name="my-label" content-class-name="my-content">kooriookami</el-descriptions-item>
+  <el-descriptions-item label="Telephone">18100000000</el-descriptions-item>
+  <el-descriptions-item label="Place">Suzhou</el-descriptions-item>
+  <el-descriptions-item label="Remarks">
+    <el-tag size="small">School</el-tag>
+  </el-descriptions-item>
+  <el-descriptions-item label="Address" :content-style="{'text-align': 'right'}">No.1188, Wuzhong Avenue, Wuzhong District, Suzhou, Jiangsu Province</el-descriptions-item>
+</el-descriptions>
+<style>
+  .my-label {
+    background: #E1F3D8;
+  }
+
+  .my-content {
+    background: #FDE2E2;
+  }
+</style>
+```
+:::
+
+### Descriptions Attributes
+| Attribute     | Description       | Type       | Accepted Values        | Default   |
+|-------------  |---------------- |---------------- |---------------------- |-------- |
+| border        | with or without border      | boolean  |          —             |    false     |
+| column        | numbers of `Descriptions Item` in one line  | number | — |    3  |
+| direction     | direction of list  | string | vertical / horizontal |    horizontal  |
+| size          | size of list    | string  |    medium / small / mini  |  — |
+| title         | title text, display on the top left    | string  |    —  |  — |
+| extra         | extra text, display on the top right    | string  |    —  |  — |
+| colon | change default props colon value of Descriptions Item   | boolean |    —  |  true |
+| labelClassName          | custom label class name         | string  |          —             |    —     |
+| contentClassName          | custom content class name         | string  |          —             |    —     |
+| labelStyle          | custom label style | object |          —             |    —     |
+| contentStyle         | custom content style | object |          —             |    —     |
+
+### Descriptions Slots
+
+| Name | Description |
+|------|--------|
+| title | custom title, display on the top left  |
+| extra | custom extra area, display on the top right  |
+
+### Descriptions Item Attributes
+| Attribute       | Description        | Type       | Accepted Values       | Default   |
+|-------------  |---------------- |---------------- |---------------------- |-------- |
+| label          | label text         | string  |          —             |    —     |
+| span          | colspan of column       | number  |          —             |    1     |
+| labelClassName          | custom label class name         | string  |          —             |    —     |
+| contentClassName          | custom content class name         | string  |          —             |    —     |
+| labelStyle          | custom label style | object |          —             |    —     |
+| contentStyle         | custom content style | object |          —             |    —     |
+
+### Descriptions Item Slots
+
+| Name | Description |
+|------|--------|
+| label | custom label  |

+ 191 - 0
examples/docs/fr-FR/descriptions.md

@@ -0,0 +1,191 @@
+## Descriptions
+
+Display multiple fields in list form.
+
+### Basic usage
+
+:::demo
+
+```html
+<el-descriptions title="User Info">
+    <el-descriptions-item label="Username">kooriookami</el-descriptions-item>
+    <el-descriptions-item label="Telephone">18100000000</el-descriptions-item>
+    <el-descriptions-item label="Place">Suzhou</el-descriptions-item>
+    <el-descriptions-item label="Remarks">
+      <el-tag size="small">School</el-tag>
+    </el-descriptions-item>
+    <el-descriptions-item label="Address">No.1188, Wuzhong Avenue, Wuzhong District, Suzhou, Jiangsu Province</el-descriptions-item>
+</el-descriptions>
+```
+:::
+
+### Sizes
+
+:::demo
+
+```html
+<template>
+  <el-radio-group v-model="size">
+    <el-radio label="">Default</el-radio>
+    <el-radio label="medium">Medium</el-radio>
+    <el-radio label="small">Small</el-radio>
+    <el-radio label="mini">Mini</el-radio>
+  </el-radio-group>
+
+  <el-descriptions class="margin-top" title="With border" :column="3" :size="size" border>
+    <template slot="extra">
+      <el-button type="primary" size="small">Operation</el-button>
+    </template>
+    <el-descriptions-item>
+      <template slot="label">
+        <i class="el-icon-user"></i>
+        Username
+      </template>
+      kooriookami
+    </el-descriptions-item>
+    <el-descriptions-item>
+      <template slot="label">
+        <i class="el-icon-mobile-phone"></i>
+        Telephone
+      </template>
+      18100000000
+    </el-descriptions-item>
+    <el-descriptions-item>
+      <template slot="label">
+        <i class="el-icon-location-outline"></i>
+        Place
+      </template>
+      Suzhou
+    </el-descriptions-item>
+    <el-descriptions-item>
+      <template slot="label">
+        <i class="el-icon-tickets"></i>
+        Remarks
+      </template>
+      <el-tag size="small">School</el-tag>
+    </el-descriptions-item>
+    <el-descriptions-item>
+      <template slot="label">
+        <i class="el-icon-office-building"></i>
+        Address
+      </template>
+      No.1188, Wuzhong Avenue, Wuzhong District, Suzhou, Jiangsu Province
+    </el-descriptions-item>
+  </el-descriptions>
+
+  <el-descriptions class="margin-top" title="Without border" :column="3" :size="size">
+    <template slot="extra">
+      <el-button type="primary" size="small">Operation</el-button>
+    </template>
+    <el-descriptions-item label="Username">kooriookami</el-descriptions-item>
+    <el-descriptions-item label="Telephone">18100000000</el-descriptions-item>
+    <el-descriptions-item label="Place">Suzhou</el-descriptions-item>
+    <el-descriptions-item label="Remarks">
+      <el-tag size="small">School</el-tag>
+    </el-descriptions-item>
+    <el-descriptions-item label="Address">No.1188, Wuzhong Avenue, Wuzhong District, Suzhou, Jiangsu Province</el-descriptions-item>
+  </el-descriptions>
+</template>
+
+<script>
+  export default {
+    data () {
+      return {
+        size: ''
+      };
+    }
+  }
+</script>
+```
+:::
+
+### Vertical List
+
+:::demo
+
+```html
+<el-descriptions title="Vertical list with border" direction="vertical" :column="4" border>
+  <el-descriptions-item label="Username">kooriookami</el-descriptions-item>
+  <el-descriptions-item label="Telephone">18100000000</el-descriptions-item>
+  <el-descriptions-item label="Place" :span="2">Suzhou</el-descriptions-item>
+  <el-descriptions-item label="Remarks">
+    <el-tag size="small">School</el-tag>
+  </el-descriptions-item>
+  <el-descriptions-item label="Address">No.1188, Wuzhong Avenue, Wuzhong District, Suzhou, Jiangsu Province</el-descriptions-item>
+</el-descriptions>
+
+<el-descriptions class="margin-top" title="Vertical list without border" :column="4" direction="vertical">
+  <el-descriptions-item label="Username">kooriookami</el-descriptions-item>
+  <el-descriptions-item label="Telephone">18100000000</el-descriptions-item>
+  <el-descriptions-item label="Place" :span="2">Suzhou</el-descriptions-item>
+  <el-descriptions-item label="Remarks">
+    <el-tag size="small">School</el-tag>
+  </el-descriptions-item>
+  <el-descriptions-item label="Address">No.1188, Wuzhong Avenue, Wuzhong District, Suzhou, Jiangsu Province</el-descriptions-item>
+</el-descriptions>
+```
+:::
+
+### Customized Style
+
+:::demo
+
+```html
+<el-descriptions title="Customized style list" :column="3" border>
+  <el-descriptions-item label="Username" label-class-name="my-label" content-class-name="my-content">kooriookami</el-descriptions-item>
+  <el-descriptions-item label="Telephone">18100000000</el-descriptions-item>
+  <el-descriptions-item label="Place">Suzhou</el-descriptions-item>
+  <el-descriptions-item label="Remarks">
+    <el-tag size="small">School</el-tag>
+  </el-descriptions-item>
+  <el-descriptions-item label="Address" :content-style="{'text-align': 'right'}">No.1188, Wuzhong Avenue, Wuzhong District, Suzhou, Jiangsu Province</el-descriptions-item>
+</el-descriptions>
+<style>
+  .my-label {
+    background: #E1F3D8;
+  }
+
+  .my-content {
+    background: #FDE2E2;
+  }
+</style>
+```
+:::
+
+### Descriptions Attributes
+| Attribute     | Description       | Type       | Accepted Values        | Default   |
+|-------------  |---------------- |---------------- |---------------------- |-------- |
+| border        | with or without border      | boolean  |          —             |    false     |
+| column        | numbers of `Descriptions Item` in one line  | number | — |    3  |
+| direction     | direction of list  | string | vertical / horizontal |    horizontal  |
+| size          | size of list    | string  |    medium / small / mini  |  — |
+| title         | title text, display on the top left    | string  |    —  |  — |
+| extra         | extra text, display on the top right    | string  |    —  |  — |
+| colon | change default props colon value of Descriptions Item   | boolean |    —  |  true |
+| labelClassName          | custom label class name         | string  |          —             |    —     |
+| contentClassName          | custom content class name         | string  |          —             |    —     |
+| labelStyle          | custom label style | object |          —             |    —     |
+| contentStyle         | custom content style | object |          —             |    —     |
+
+### Descriptions Slots
+
+| Name | Description |
+|------|--------|
+| title | custom title, display on the top left  |
+| extra | custom extra area, display on the top right  |
+
+### Descriptions Item Attributes
+| Attribute       | Description        | Type       | Accepted Values       | Default   |
+|-------------  |---------------- |---------------- |---------------------- |-------- |
+| label          | label text         | string  |          —             |    —     |
+| span          | colspan of column       | number  |          —             |    1     |
+| labelClassName          | custom label class name         | string  |          —             |    —     |
+| contentClassName          | custom content class name         | string  |          —             |    —     |
+| labelStyle          | custom label style | object |          —             |    —     |
+| contentStyle         | custom content style | object |          —             |    —     |
+
+### Descriptions Item Slots
+
+| Name | Description |
+|------|--------|
+| label | custom label  |

+ 191 - 0
examples/docs/zh-CN/descriptions.md

@@ -0,0 +1,191 @@
+## Descriptions 描述列表
+
+列表形式展示多个字段。
+
+### 基础用法
+
+:::demo
+
+```html
+<el-descriptions title="用户信息">
+    <el-descriptions-item label="用户名">kooriookami</el-descriptions-item>
+    <el-descriptions-item label="手机号">18100000000</el-descriptions-item>
+    <el-descriptions-item label="居住地">苏州市</el-descriptions-item>
+    <el-descriptions-item label="备注">
+      <el-tag size="small">学校</el-tag>
+    </el-descriptions-item>
+    <el-descriptions-item label="联系地址">江苏省苏州市吴中区吴中大道 1188 号</el-descriptions-item>
+</el-descriptions>
+```
+:::
+
+### 不同尺寸
+
+:::demo
+
+```html
+<template>
+  <el-radio-group v-model="size">
+    <el-radio label="">默认</el-radio>
+    <el-radio label="medium">中等</el-radio>
+    <el-radio label="small">小型</el-radio>
+    <el-radio label="mini">超小</el-radio>
+  </el-radio-group>
+
+  <el-descriptions class="margin-top" title="带边框列表" :column="3" :size="size" border>
+    <template slot="extra">
+      <el-button type="primary" size="small">操作</el-button>
+    </template>
+    <el-descriptions-item>
+      <template slot="label">
+        <i class="el-icon-user"></i>
+        用户名
+      </template>
+      kooriookami
+    </el-descriptions-item>
+    <el-descriptions-item>
+      <template slot="label">
+        <i class="el-icon-mobile-phone"></i>
+        手机号
+      </template>
+      18100000000
+    </el-descriptions-item>
+    <el-descriptions-item>
+      <template slot="label">
+        <i class="el-icon-location-outline"></i>
+        居住地
+      </template>
+      苏州市
+    </el-descriptions-item>
+    <el-descriptions-item>
+      <template slot="label">
+        <i class="el-icon-tickets"></i>
+        备注
+      </template>
+      <el-tag size="small">学校</el-tag>
+    </el-descriptions-item>
+    <el-descriptions-item>
+      <template slot="label">
+        <i class="el-icon-office-building"></i>
+        联系地址
+      </template>
+      江苏省苏州市吴中区吴中大道 1188 号
+    </el-descriptions-item>
+  </el-descriptions>
+
+  <el-descriptions class="margin-top" title="无边框列表" :column="3" :size="size">
+    <template slot="extra">
+      <el-button type="primary" size="small">操作</el-button>
+    </template>
+    <el-descriptions-item label="用户名">kooriookami</el-descriptions-item>
+    <el-descriptions-item label="手机号">18100000000</el-descriptions-item>
+    <el-descriptions-item label="居住地">苏州市</el-descriptions-item>
+    <el-descriptions-item label="备注">
+      <el-tag size="small">学校</el-tag>
+    </el-descriptions-item>
+    <el-descriptions-item label="联系地址">江苏省苏州市吴中区吴中大道 1188 号</el-descriptions-item>
+  </el-descriptions>
+</template>
+
+<script>
+  export default {
+    data () {
+      return {
+        size: ''
+      };
+    }
+  }
+</script>
+```
+:::
+
+### 垂直列表
+
+:::demo
+
+```html
+<el-descriptions title="垂直带边框列表" direction="vertical" :column="4" border>
+  <el-descriptions-item label="用户名">kooriookami</el-descriptions-item>
+  <el-descriptions-item label="手机号">18100000000</el-descriptions-item>
+  <el-descriptions-item label="居住地" :span="2">苏州市</el-descriptions-item>
+  <el-descriptions-item label="备注">
+    <el-tag size="small">学校</el-tag>
+  </el-descriptions-item>
+  <el-descriptions-item label="联系地址">江苏省苏州市吴中区吴中大道 1188 号</el-descriptions-item>
+</el-descriptions>
+
+<el-descriptions class="margin-top" title="垂直无边框列表" :column="4" direction="vertical">
+  <el-descriptions-item label="用户名">kooriookami</el-descriptions-item>
+  <el-descriptions-item label="手机号">18100000000</el-descriptions-item>
+  <el-descriptions-item label="居住地" :span="2">苏州市</el-descriptions-item>
+  <el-descriptions-item label="备注">
+    <el-tag size="small">学校</el-tag>
+  </el-descriptions-item>
+  <el-descriptions-item label="联系地址">江苏省苏州市吴中区吴中大道 1188 号</el-descriptions-item>
+</el-descriptions>
+```
+:::
+
+### 自定义样式
+
+:::demo
+
+```html
+<el-descriptions title="自定义样式列表" :column="3" border>
+  <el-descriptions-item label="用户名" label-class-name="my-label" content-class-name="my-content">kooriookami</el-descriptions-item>
+  <el-descriptions-item label="手机号">18100000000</el-descriptions-item>
+  <el-descriptions-item label="居住地">苏州市</el-descriptions-item>
+  <el-descriptions-item label="备注">
+    <el-tag size="small">学校</el-tag>
+  </el-descriptions-item>
+  <el-descriptions-item label="联系地址" :contentStyle="{'text-align': 'right'}">江苏省苏州市吴中区吴中大道 1188 号</el-descriptions-item>
+</el-descriptions>
+<style>
+  .my-label {
+    background: #E1F3D8;
+  }
+
+  .my-content {
+    background: #FDE2E2;
+  }
+</style>
+```
+:::
+
+### Descriptions Attributes
+| 参数          | 说明            | 类型            | 可选值                 | 默认值   |
+|-------------  |---------------- |---------------- |---------------------- |-------- |
+| border        | 是否带有边框         | boolean  |          —             |    false     |
+| column        | 一行 `Descriptions Item` 的数量  | number | — |    3  |
+| direction     | 排列的方向  | string | vertical / horizontal |    horizontal  |
+| size          | 列表的尺寸    | string  |    medium / small / mini  |  — |
+| title         | 标题文本,显示在左上方    | string  |    —  |  — |
+| extra         | 操作区文本,显示在右上方    | string  |    —  |  — |
+| colon         | 是否显示冒号    | boolean  |    —  |  true |
+| labelClassName | 自定义标签类名    | string |    —  |  — |
+| contentClassName | 自定义内容类名    | string |    —  | — |
+| labelStyle | 自定义标签样式 | object |    —  | — |
+| contentStyle | 自定义内容样式    | object |    —  | — |
+
+### Descriptions Slots
+
+| Name | 说明 |
+|------|--------|
+| title | 自定义标题,显示在左上方  |
+| extra | 自定义操作区,显示在右上方  |
+
+### Descriptions Item Attributes
+| 参数          | 说明            | 类型            | 可选值                 | 默认值   |
+|-------------  |---------------- |---------------- |---------------------- |-------- |
+| label          | 标签文本         | string  |          —             |    —     |
+| span          | 列的数量         | number  |          —             |    1     |
+| labelClassName | 自定义标签类名    | string |    —  |  — |
+| contentClassName | 自定义内容类名    | string |    —  | — |
+| labelStyle | 自定义标签样式 | object |    —  | — |
+| contentStyle | 自定义内容样式    | object |    —  | — |
+
+### Descriptions Item Slots
+
+| Name | 说明 |
+|------|--------|
+| label | 自定义标签文本  |

+ 16 - 0
examples/nav.config.json

@@ -184,6 +184,10 @@
             {
               "path": "/empty",
               "title": "Empty 空状态"
+            },
+            {
+              "path": "/descriptions",
+              "title": "Descriptions 描述列表"
             }
           ]
         },
@@ -486,6 +490,10 @@
             {
               "path": "/empty",
               "title": "Empty"
+            },
+            {
+              "path": "/descriptions",
+              "title": "Descriptions"
             }
           ]
         },
@@ -792,6 +800,10 @@
             {
               "path": "/empty",
               "title": "Empty"
+            },
+            {
+              "path": "/descriptions",
+              "title": "Descriptions"
             }
           ]
         },
@@ -1098,6 +1110,10 @@
             {
               "path": "/empty",
               "title": "Empty"
+            },
+            {
+              "path": "/descriptions",
+              "title": "Descriptions"
             }
           ]
         },

+ 8 - 0
packages/descriptions-item/index.js

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

+ 8 - 0
packages/descriptions/index.js

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

+ 30 - 0
packages/descriptions/src/description-item.js

@@ -0,0 +1,30 @@
+export default {
+  name: 'ElDescriptionsItem',
+  props: {
+    label: {
+      type: String,
+      default: ''
+    },
+    span: {
+      type: Number,
+      default: 1
+    },
+    contentClassName: {
+      type: String,
+      default: ''
+    },
+    contentStyle: {
+      type: Object
+    },
+    labelClassName: {
+      type: String,
+      default: ''
+    },
+    labelStyle: {
+      type: Object
+    }
+  },
+  render() {
+    return null;
+  }
+};

+ 115 - 0
packages/descriptions/src/descriptions-row.js

@@ -0,0 +1,115 @@
+export default {
+  name: 'ElDescriptionsRow',
+  props: {
+    row: {
+      type: Array
+    }
+  },
+  inject: ['elDescriptions'],
+  render(h) {
+    const { elDescriptions } = this;
+    const row = (this.row || []).map(item => {
+      return {
+        ...item,
+        label: item.slots.label || item.props.label,
+        ...['labelClassName', 'contentClassName', 'labelStyle', 'contentStyle'].reduce((res, key) => {
+          res[key] = item.props[key] || elDescriptions[key];
+          return res;
+        }, {})
+      };
+    });
+    if (elDescriptions.direction === 'vertical') {
+      return (
+        <tbody>
+          <tr class="el-descriptions-row">
+            {
+              row.map(item => {
+                return (
+                  <th
+                    class={{
+                      'el-descriptions-item__label': true,
+                      'has-colon': elDescriptions.border ? false : elDescriptions.colon,
+                      'is-bordered-label': elDescriptions.border,
+                      [item.labelClassName]: true
+                    }}
+                    style={item.labelStyle}
+                    colSpan={item.props.span}
+                  >{item.label}</th>
+                );
+              })
+            }
+          </tr>
+          <tr class="el-descriptions-row">
+            {
+              row.map(item =>{
+                return (
+                  <td
+                    class="el-descriptions-item__content"
+                    class={['el-descriptions-item__content', item.contentClassName]}
+                    style={item.contentStyle}
+                    colSpan={item.props.span}
+                  >{item.slots.default}</td>
+                );
+              })
+            }
+          </tr>
+        </tbody>
+      );
+    }
+    if (elDescriptions.border) {
+      return (
+        <tbody>
+          <tr class="el-descriptions-row">
+            {
+              row.map(item=> {
+                return ([
+                  <th
+                    class={{
+                      'el-descriptions-item__label': true,
+                      'is-bordered-label': elDescriptions.border,
+                      [item.labelClassName]: true
+                    }}
+                    style={item.labelStyle}
+                    colSpan="1"
+                  >{item.label}</th>,
+                  <td
+                    class={['el-descriptions-item__content', item.contentClassName]}
+                    style={item.contentStyle}
+                    colSpan={item.props.span * 2 - 1}
+                  >{item.slots.default}</td>
+                ]);
+              })
+            }
+          </tr>
+        </tbody>
+      );
+    }
+    return (
+      <tbody>
+        <tr class="el-descriptions-row">
+          {
+            row.map(item=> {
+              return (
+                <td class="el-descriptions-item" colSpan={item.props.span}>
+                  <div class="el-descriptions-item__container">
+                    <span
+                      class={{
+                        'el-descriptions-item__label': true,
+                        'has-colon': elDescriptions.colon,
+                        [item.labelClassName]: true
+                      }}
+                      style={item.labelStyle}
+                    >{item.props.label}</span>
+                    <span
+                      class={['el-descriptions-item__content', item.contentClassName]}
+                      style={item.contentStyle}
+                    >{item.slots.default}</span>
+                  </div>
+                </td>);
+            })
+          }
+        </tr>
+      </tbody>
+    );
+  }
+};

+ 180 - 0
packages/descriptions/src/index.js

@@ -0,0 +1,180 @@
+import DescriptionsRow from './descriptions-row';
+import { isFunction } from 'element-ui/src/utils/types';
+
+export default {
+  name: 'ElDescriptions',
+  components: {
+    [DescriptionsRow.name]: DescriptionsRow
+  },
+  props: {
+    border: {
+      type: Boolean,
+      default: false
+    },
+    column: {
+      type: Number,
+      default: 3
+    },
+    direction: {
+      type: String,
+      default: 'horizontal'
+    },
+    size: {
+      type: String
+      // validator: isValidComponentSize,
+    },
+    title: {
+      type: String,
+      default: ''
+    },
+    extra: {
+      type: String,
+      default: ''
+    },
+    labelStyle: {
+      type: Object
+    },
+    contentStyle: {
+      type: Object
+    },
+    labelClassName: {
+      type: String,
+      default: ''
+    },
+    contentClassName: {
+      type: String,
+      default: ''
+    },
+    colon: {
+      type: Boolean,
+      default: true
+    }
+  },
+  computed: {
+    descriptionsSize() {
+      return this.size || (this.$ELEMENT || {}).size;
+    }
+  },
+  provide() {
+    return {
+      elDescriptions: this
+    };
+  },
+  methods: {
+    getOptionProps(vnode) {
+      if (vnode.componentOptions) {
+        const componentOptions = vnode.componentOptions;
+        const { propsData = {}, Ctor = {} } = componentOptions;
+        const props = (Ctor.options || {}).props || {};
+        const res = {};
+        for (const k in props) {
+          const v = props[k];
+          const defaultValue = v.default;
+          if (defaultValue !== undefined) {
+            res[k] = isFunction(defaultValue) ? defaultValue.call(vnode) : defaultValue;
+          }
+        }
+        return { ...res, ...propsData };
+      }
+      return {};
+    },
+    getSlots(vnode) {
+      let componentOptions = vnode.componentOptions || {};
+      const children = vnode.children || componentOptions.children || [];
+      const slots = {};
+      children.forEach(child => {
+        if (!this.isEmptyElement(child)) {
+          const name = (child.data && child.data.slot) || 'default';
+          slots[name] = slots[name] || [];
+          if (child.tag === 'template') {
+            slots[name].push(child.children);
+          } else {
+            slots[name].push(child);
+          }
+        }
+      });
+      return { ...slots };
+    },
+    isEmptyElement(c) {
+      return !(c.tag || (c.text && c.text.trim() !== ''));
+    },
+    filledNode(node, span, count, isLast = false) {
+      if (!node.props) {
+        node.props = {};
+      }
+      if (span > count) {
+        node.props.span = count;
+      }
+      if (isLast) {
+        // set the max span, cause of the last td
+        node.props.span = count;
+      }
+      return node;
+    },
+    getRows() {
+      const children = ((this.$slots.default || []).filter(vnode => vnode.tag &&
+            vnode.componentOptions && vnode.componentOptions.Ctor.options.name === 'ElDescriptionsItem'));
+      const nodes = children.map(vnode => {
+        return {
+          props: this.getOptionProps(vnode),
+          slots: this.getSlots(vnode),
+          vnode
+        };
+      });
+      const rows = [];
+      let temp = [];
+      let count = this.column;
+
+      nodes.forEach((node, index) => {
+        const span = node.props.span || 1;
+
+        if (index === children.length - 1) {
+          temp.push(this.filledNode(node, span, count, true));
+          rows.push(temp);
+          return;
+        }
+
+        if (span < count) {
+          count -= span;
+          temp.push(node);
+        } else {
+          temp.push(this.filledNode(node, span, count));
+          rows.push(temp);
+          count = this.column;
+          temp = [];
+        }
+      });
+
+      return rows;
+    }
+  },
+  render() {
+    const { title, extra, border, descriptionsSize, $slots } = this;
+    const rows = this.getRows();
+
+    return (
+      <div class="el-descriptions">
+        {
+          (title || extra || $slots.title || $slots.extra)
+            ? <div class="el-descriptions__header">
+              <div class="el-descriptions__title">
+                { $slots.title ? $slots.title : title}
+              </div>
+              <div class="el-descriptions__extra">
+                { $slots.extra ? $slots.extra : extra }
+              </div>
+            </div>
+            : null
+        }
+
+        <div class="el-descriptions__body">
+          <table class={[{'is-bordered': border}, descriptionsSize ? `el-descriptions--${descriptionsSize}` : '']}>
+            {rows.map(row => (
+              <DescriptionsRow row={row}></DescriptionsRow>
+            ))}
+          </table>
+        </div>
+      </div>
+    );
+  }
+};

+ 7 - 0
packages/theme-chalk/src/common/var.scss

@@ -971,6 +971,13 @@ $--empty-image-width: 160px !default;
 $--empty-description-margin-top: 20px !default;
 $--empty-bottom-margin-top: 20px !default;
 
+/* Descriptions
+-------------------------- */
+$--descriptions-header-margin-bottom: 20px !default;
+$--descriptions-title-font-size: 16px !default;
+$--descriptions-table-border: 1px solid $--border-color-lighter !default;
+$--descriptions-item-bordered-label-background: #fafafa !default;
+
 /* Skeleton 
 --------------------------*/
 $--skeleton-color: #f2f2f2 !default;

+ 32 - 0
packages/theme-chalk/src/descriptions-item.scss

@@ -0,0 +1,32 @@
+@import 'mixins/mixins';
+@import 'common/var';
+
+@include b(descriptions-item) {
+  
+  @include e(container) {
+    display: flex;
+  }
+
+  @include e(label) {
+    &.has-colon {
+      &::after {
+        content: ':';
+        position: relative;
+        top: -0.5px;
+      }
+    }
+    &.is-bordered-label {
+      font-weight: bold;
+      color: $--color-text-secondary;
+      background: $--descriptions-item-bordered-label-background;
+    }
+
+    &:not(.is-bordered-label) {
+      margin-right: 10px;
+    }
+  }
+
+  @include e(content) {
+
+  }
+}

+ 111 - 0
packages/theme-chalk/src/descriptions.scss

@@ -0,0 +1,111 @@
+@import 'mixins/mixins';
+@import 'common/var';
+@import 'descriptions-item';
+
+@include b(descriptions) {
+  box-sizing: border-box;
+  font-size: $--font-size-base;
+  color: $--color-text-primary;
+
+  @include e(header) {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    margin-bottom: $--descriptions-header-margin-bottom;
+
+    @include e(title) {
+      font-size: $--descriptions-title-font-size;
+      font-weight: bold;
+    }
+  }
+
+  @include e(body) {
+    color: $--color-text-regular;
+    background-color: $--color-white;
+
+    table {
+      border-collapse: collapse;
+      width: 100%;
+      table-layout: fixed;
+
+      th, td {
+        box-sizing: border-box;
+        text-align: left;
+        font-weight: normal;
+        line-height: 1.5;
+
+        @include when(left) {
+          text-align: left;
+        }
+
+        @include when(center) {
+          text-align: center;
+        }
+
+        @include when(right) {
+          text-align: right;
+        }
+      }
+    }
+  }
+
+  .is-bordered {
+    table-layout: auto;
+    th, td {
+      border: $--descriptions-table-border;
+      padding: 12px 10px;
+    }
+  }
+
+  :not(.is-bordered) {
+    th, td {
+      padding-bottom: 12px;
+    }
+  }
+
+  @include m(medium) {
+    &.is-bordered {
+      th, td {
+        padding: 10px;
+      }
+    }
+
+    &:not(.is-bordered) {
+      th, td {
+        padding-bottom: 10px;
+      }
+    }
+  }
+
+  @include m(small) {
+    font-size: 12px;
+
+    &.is-bordered {
+      th, td {
+        padding: 8px 10px;
+      }
+    }
+
+    &:not(.is-bordered) {
+      th, td {
+        padding-bottom: 8px;
+      }
+    }
+  }
+
+  @include m(mini) {
+    font-size: 12px;
+
+    &.is-bordered {
+      th, td {
+        padding: 6px 10px;
+      }
+    }
+
+    &:not(.is-bordered) {
+      th, td {
+        padding-bottom: 6px;
+      }
+    }
+  }
+}

+ 2 - 0
packages/theme-chalk/src/index.scss

@@ -81,3 +81,5 @@
 @import "./skeleton.scss";
 @import "./skeleton-item.scss";
 @import "./empty.scss";
+@import "./descriptions.scss";
+@import "./descriptions-item.scss";

+ 7 - 1
src/index.js

@@ -85,6 +85,8 @@ import Popconfirm from '../packages/popconfirm/index.js';
 import Skeleton from '../packages/skeleton/index.js';
 import SkeletonItem from '../packages/skeleton-item/index.js';
 import Empty from '../packages/empty/index.js';
+import Descriptions from '../packages/descriptions/index.js';
+import DescriptionsItem from '../packages/descriptions-item/index.js';
 import locale from 'element-ui/src/locale';
 import CollapseTransition from 'element-ui/src/transitions/collapse-transition';
 
@@ -169,6 +171,8 @@ const components = [
   Skeleton,
   SkeletonItem,
   Empty,
+  Descriptions,
+  DescriptionsItem,
   CollapseTransition
 ];
 
@@ -293,5 +297,7 @@ export default {
   Popconfirm,
   Skeleton,
   SkeletonItem,
-  Empty
+  Empty,
+  Descriptions,
+  DescriptionsItem
 };

+ 159 - 0
test/unit/specs/descriptions.spec.js

@@ -0,0 +1,159 @@
+// import Descriptions from 'packages/descriptions';
+// import DescriptionsItem from '../src/description-item';
+
+// import { createTest, destroyVM, createVue, waitImmediate, wait} from '../util';
+import { destroyVM, createVue, waitImmediate } from '../util';
+
+describe('Descriptions', () => {
+  let vm;
+
+  afterEach(() => {
+    destroyVM(vm);
+  });
+
+  it('render test', () => {
+    vm = createVue(
+      {
+        template: `
+          <el-descriptions title="title" extra="extra">
+            <el-descriptions-item v-for="item in 4"></el-descriptions-item>
+          </el-descriptions>
+        `
+      },
+      true
+    );
+    const el = vm.$el;
+    expect(el.querySelector('.el-descriptions__title').textContent).to.equal('title');
+    expect(el.querySelector('.el-descriptions__extra').textContent).to.equal('extra');
+    expect(el.querySelectorAll('.el-descriptions-item__label').length).to.equal(4);
+  });
+
+  it('should render border props', () => {
+    vm = createVue(
+      {
+        template: `
+          <el-descriptions border>
+            <el-descriptions-item v-for="item in 3" :label="item">{{ item }}</el-descriptions-item>
+          </el-descriptions
+        `
+      },
+      true
+    );
+    const el = vm.$el;
+    expect(Array.from(el.querySelector('table').classList)).to.contain('is-bordered');
+  });
+
+  it('should render class props', () => {
+    vm = createVue(
+      {
+        template: `
+          <el-descriptions border label-class-name="label-class-name" content-class-name="content-class-name">
+            <el-descriptions-item v-for="item in 3" :label="item">{{ item }}</el-descriptions-item>
+          </el-descriptions>
+        `
+      },
+      true);
+
+    expect(Array.from(vm.$el.querySelector('.el-descriptions-item__label').classList)).to.contain('label-class-name');
+    expect(Array.from(vm.$el.querySelector('.el-descriptions-item__content').classList)).to.contain('content-class-name');
+  });
+
+  it('should render column props', async() => {
+    vm = createVue({
+      template: `
+      <el-descriptions :column="5" :border="border">
+        <el-descriptions-item v-for="item in 10" :label="item">{{ item }}</el-descriptions-item>
+      </el-descriptions>
+    `,
+      data() {
+        return {
+          border: false
+        };
+      }
+    }, true);
+
+    expect(vm.$el.querySelector('tr').children.length).to.equal(5);
+    vm.border = true;
+    await waitImmediate();
+    expect(vm.$el.querySelector('tr').children.length).to.equal(10);
+  });
+
+  it('should render direction props', async() => {
+    vm = createVue({
+
+      template: `
+      <el-descriptions :column="5" :direction="direction" border>
+        <el-descriptions-item v-for="item in 10" :label="item">{{ item }}</el-descriptions-item>
+      </el-descriptions>
+    `,
+      data() {
+        return {
+          direction: 'horizontal'
+        };
+      }
+    }, true);
+
+    expect(vm.$el.querySelector('tr').children.length).to.equal(10);
+    expect(vm.$el.querySelectorAll('tr')[0].children[0].innerHTML).to.equal(vm.$el.querySelectorAll('tr')[0].children[1].innerHTML);
+    vm.direction = 'vertical';
+    await waitImmediate();
+    expect(vm.$el.querySelector('tr').children.length).to.equal(5);
+    expect(vm.$el.querySelectorAll('tr')[0].children[0].innerHTML).to.equal(vm.$el.querySelectorAll('tr')[1].children[0].innerHTML);
+  });
+
+  it('should render title slots', async() => {
+    vm = createVue({
+      template: `
+      <el-descriptions>
+        <template slot="title">title</template>
+        <el-descriptions-item v-for="item in 10" :label="item">{{ item }}</el-descriptions-item>
+      </el-descriptions>
+    `
+    }, true);
+
+    expect(vm.$el.querySelector('.el-descriptions__title').innerText).to.equal('title');
+  });
+
+  it('should render span props', async() => {
+    vm = createVue({
+      template: `
+        <el-descriptions :column="3">
+          <el-descriptions-item label="1">1</el-descriptions-item>
+          <el-descriptions-item label="2" :span="2">2</el-descriptions-item>
+          <el-descriptions-item label="3">3</el-descriptions-item>
+        </el-descriptions>
+      `
+    }, true);
+
+    expect(vm.$el.querySelectorAll('td')[1].getAttribute('colSpan')).to.equal('2');
+  });
+
+  it('re-rendered when slots is updated', async() => {
+    const CHANGE_VALUE = 'company';
+    vm = createVue({
+      template: `
+        <div>
+          <el-descriptions v-for="(remark,index) in remarks" :key="index" :title="remark">
+            <el-descriptions-item label="remark">
+              <el-tag size="small">{{remark}}</el-tag>
+            </el-descriptions-item>
+          </el-descriptions>
+          <button @click="onClick">click</button>
+        </div>
+      `,
+      data() {
+        return {
+          remarks: ['school', 'hospital']
+        };
+      },
+      methods: {
+        onClick() {
+          this.$set(this.remarks, 0, CHANGE_VALUE);
+        }
+      }
+    }, true);
+    vm.$el.querySelector('button').click();
+    await waitImmediate();
+    expect(vm.$el.querySelector('.el-tag').innerText).to.equal(CHANGE_VALUE);
+  });
+});

+ 37 - 0
types/descriptions-item.d.ts

@@ -0,0 +1,37 @@
+import { ElementUIComponent } from './component'
+import { VNode } from 'vue'
+
+interface ElDescriptionsItemSlots {
+  /* label slot: custom label */
+  label: VNode[]
+
+  /* default slot: custom content */
+  default: VNode[]
+
+  [key: string]: VNode[]
+}
+
+/** description item. **/
+export declare class ElDescriptionsItem extends ElementUIComponent {
+
+  /* label text */
+  label: string
+
+  /*  the number of columns included */
+  span: number 
+
+  /* custom label class name */
+  labelClassName: string
+
+  /* custom content class name */
+  contentClassName: string
+
+  /* custom label style */
+  labelStyle: object
+
+  /* custom content style */
+  contentStyle: object
+
+  $slots: ElDescriptionsItemSlots
+
+}

+ 52 - 0
types/descriptions.d.ts

@@ -0,0 +1,52 @@
+import { ElementUIComponent } from './component'
+import { VNode } from 'vue'
+
+interface ElDescriptionsSlots {
+  /* title slot: custom title, display on the top left */
+  title: VNode[]
+
+  /* title slot: custom extra area, display on the top right */
+  extra: VNode[]
+
+  [key: string]: VNode[]
+}
+
+/** Display multiple fields in list form. **/
+export declare class ElDescriptions extends ElementUIComponent {
+
+  /* with or without border */
+  border: boolean
+  
+  /* numbers of Descriptions Item in one line */
+  column: number
+
+  /* direction of list */
+  direction: 'vertical' | 'horizontal'
+
+  /* size of list */
+  size: 'medium' | 'small' | 'mini'
+
+  /* title text, display on the top left */
+  title: string
+
+  /* extra text, display on the top right */
+  extra: string
+
+  /* change default props colon value of Descriptions Item */
+  colon: boolean
+
+  /* custom label class name */
+  labelClassName: string
+
+  /* custom content class name */
+  contentClassName: string
+
+  /* custom label style */
+  labelStyle: object
+
+  /* custom content style */
+  contentStyle: object
+
+  $slots: ElDescriptionsSlots
+
+}

+ 8 - 0
types/element-ui.d.ts

@@ -85,6 +85,8 @@ import { ElSkeletonItem } from './skeleton-item'
 import { ElCascaderPanel } from './cascader-panel'
 import { ElEmpty } from './empty'
 import { ElSpinner } from './spinner'
+import { ElDescriptions } from './descriptions'
+import { ElDescriptionsItem } from './descriptions-item'
 
 export interface InstallationOptions {
   locale: any,
@@ -364,3 +366,9 @@ export class Empty extends ElEmpty {}
 
 /** Spinner Component */
 export class Spinner extends ElSpinner {}
+
+/** Description Component */
+export class Descripitions extends ElDescriptions {}
+
+/** Description Item Component */
+export class DescripitionsItem extends ElDescriptionsItem {}