Avatar: Add avatar component (#16144)

* add avatar component

* 1. add test 2. add types 3. refine doc 4. add img attr

* add props in types and doc

* refine how image fit its container

* fix doc

* refine doc

* change default background color

* remote style demo from doc

* add theme

* add demo on theme preview and change var name
pull/16135/head
luckyCao 2019-06-24 16:37:17 +08:00 committed by Zhi Cun
parent c588b64fa1
commit 6f9ce3accb
18 changed files with 1005 additions and 3 deletions

View File

@ -77,5 +77,6 @@
"backtop": "./packages/backtop/index.js", "backtop": "./packages/backtop/index.js",
"infinite-scroll": "./packages/infinite-scroll/index.js", "infinite-scroll": "./packages/infinite-scroll/index.js",
"page-header": "./packages/page-header/index.js", "page-header": "./packages/page-header/index.js",
"cascader-panel": "./packages/cascader-panel/index.js" "cascader-panel": "./packages/cascader-panel/index.js",
"avatar": "./packages/avatar/index.js"
} }

View File

@ -25,6 +25,10 @@
.el-carousel__item:nth-child(2n + 1) { .el-carousel__item:nth-child(2n + 1) {
background-color: #d3dce6; background-color: #d3dce6;
} }
.el-avatar:not(:last-child) {
margin-right: 20px;
}
} }
</style> </style>
<template> <template>
@ -140,7 +144,7 @@
</el-row> </el-row>
<h4>Rate</h4> <h4>Rate</h4>
<el-row> <el-row>
<el-rate class="demo-line" v-model="rate"></el-rate> <el-rate class="demo-line" v-model="rate"></el-rate>
<el-rate <el-rate
class="demo-line" class="demo-line"
v-model="rate" v-model="rate"
@ -354,6 +358,12 @@
</el-collapse-item> </el-collapse-item>
</el-collapse> </el-collapse>
</el-row> </el-row>
<h4>Avatar</h4>
<el-row>
<el-avatar icon="el-icon-user-solid"/>
<el-avatar> avatar </el-avatar>
<el-avatar shape="square" :size="60" fit="contain" :src="avatarData.url"></el-avatar>
</el-row>
</div> </div>
</template> </template>
<script> <script>
@ -511,6 +521,9 @@ export default {
defaultTreeProps: { defaultTreeProps: {
children: 'children', children: 'children',
label: 'label' label: 'label'
},
avatarData: {
url: 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg'
} }
}; };
} }

View File

@ -0,0 +1,62 @@
.demo-avatar {
&.demo-basic {
text-align: center;
.demo-basic--circle, .demo-basic--square {
display: flex;
justify-content: space-between;
align-items: center;
.block {
flex: 1;
}
.block:not(:last-child) {
border-right: 1px solid rgba(224, 230, 237, 0.5);
}
}
}
.sub-title {
margin-bottom: 10px;
font-size: 14px;
color: #8492a6;
}
.el-col:not(:last-child) {
border-right: 1px solid rgba(224,230,237,.5);
}
.demo-type {
display: flex;
>div {
flex: 1;
text-align: center;
}
>div:not(:last-child) {
border-right: 1px solid rgba(224,230,237,.5);
}
}
.demo-fit {
display: flex;
text-align: center;
justify-content: space-between;
.block {
flex: 1;
display: flex;
flex-direction: column;
flex-grow: 0;
}
.title {
margin-bottom: 10px;
font-size: 14px;
color: #8492a6;
}
}
}

View File

@ -42,3 +42,5 @@
@import "./divider.scss"; @import "./divider.scss";
@import "./image.scss"; @import "./image.scss";
@import "./infiniteScroll.scss"; @import "./infiniteScroll.scss";
@import "./avatar.scss";

View File

@ -0,0 +1,145 @@
## Avatar avatar
Avatars can be used to represent people or objects. It supports images, Icons, or characters.
### Basic
use `shape` and `size` prop to set avatar's shape and size
:::demo
```html
<template>
<el-row class="demo-avatar demo-basic">
<el-col :span="12">
<div class="sub-title">circle</div>
<div class="demo-basic--circle">
<div class="block"><el-avatar :size="50" :src="circleUrl"></el-avatar></div>
<div class="block" v-for="size in sizeList" :key="size">
<el-avatar :size="size" :src="circleUrl"></el-avatar>
</div>
</div>
</el-col>
<el-col :span="12">
<div class="sub-title">square</div>
<div class="demo-basic--circle">
<div class="block"><el-avatar shape="square" :size="50" :src="squareUrl"></el-avatar></div>
<div class="block" v-for="size in sizeList" :key="size">
<el-avatar shape="square" :size="size" :src="squareUrl"></el-avatar>
</div>
</div>
</el-col>
</el-row>
</template>
<script>
export default {
data () {
return {
circleUrl: "https://cube.elemecdn.com/3/7c/3ea6beec64369c2642b92c6726f1epng.png",
squareUrl: "https://cube.elemecdn.com/9/c2/f0ee8a3c7c9638a54940382568c9dpng.png",
sizeList: ["large", "medium", "small"]
}
}
}
</script>
```
:::
### Types
It supports images, Icons, or characters
:::demo
```html
<template>
<div class="demo-type">
<div>
<el-avatar icon="el-icon-user-solid"></el-avatar>
</div>
<div>
<el-avatar src="https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png"></el-avatar>
</div>
<div>
<el-avatar> user </el-avatar>
</div>
</div>
</template>
```
:::
### Fallback when image load error
fallback when image load error
:::demo
```html
<template>
<div class="demo-type">
<el-avatar :size="60" src="https://empty" @error="errorHandler">
<img src="https://cube.elemecdn.com/e/fd/0fc7d20532fdaf769a25683617711png.png"/>
</el-avatar>
</div>
</template>
<script>
export default {
methods: {
errorHandler() {
return true
}
}
}
</script>
```
:::
### How the image fit its container
Set how the image fit its container for an image avatar, same as [object-fit](https://developer.mozilla.org/en-US/docs/Web/CSS/object-fit).
:::demo
```html
<template>
<div class="demo-fit">
<div class="block" v-for="fit in fits" :key="fit">
<span class="title">{{ fit }}</span>
<el-avatar shape="square" :size="100" :fit="fit" :src="url"></el-avatar>
</div>
</div>
</template>
<script>
export default {
data() {
return {
fits: ['fill', 'contain', 'cover', 'none', 'scale-down'],
url: 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg'
}
}
}
</script>
```
:::
### Attributes
| Attribute | Description | Type | Accepted Values | Default |
| ----------------- | -------------------------------- | --------------- | ------ | ------ |
| icon | set representation type to Icon, more info on Icon Component | string | | |
| size | set avatar size | number/string | number / large / medium / small | large |
| shape | set avatar shape | string | circle / square | circle |
| src | the address of the image for an image avatar | string | | |
| srcSet | A list of one or more strings separated by commas indicating a set of possible image sources for the user agent to use | string | | |
| alt | This attribute defines an alternative text description of the image | string | | |
| fit | set how the image fit its container for an image avatar | string | fill / contain / cover / none / scale-down | cover |
### Events
| Event Name | Description | Parameters |
| ------ | ------------------ | -------- |
| error | handler when img load error, return false to prevent default fallback behavior |(e: Event) |
### Slot
| Slot Name | Description |
| default | customize avatar content |

145
examples/docs/es/avatar.md Normal file
View File

@ -0,0 +1,145 @@
## Avatar avatar
Avatars can be used to represent people or objects. It supports images, Icons, or characters.
### Basic
use `shape` and `size` prop to set avatar's shape and size
:::demo
```html
<template>
<el-row class="demo-avatar demo-basic">
<el-col :span="12">
<div class="sub-title">circle</div>
<div class="demo-basic--circle">
<div class="block"><el-avatar :size="50" :src="circleUrl"></el-avatar></div>
<div class="block" v-for="size in sizeList" :key="size">
<el-avatar :size="size" :src="circleUrl"></el-avatar>
</div>
</div>
</el-col>
<el-col :span="12">
<div class="sub-title">square</div>
<div class="demo-basic--circle">
<div class="block"><el-avatar shape="square" :size="50" :src="squareUrl"></el-avatar></div>
<div class="block" v-for="size in sizeList" :key="size">
<el-avatar shape="square" :size="size" :src="squareUrl"></el-avatar>
</div>
</div>
</el-col>
</el-row>
</template>
<script>
export default {
data () {
return {
circleUrl: "https://cube.elemecdn.com/3/7c/3ea6beec64369c2642b92c6726f1epng.png",
squareUrl: "https://cube.elemecdn.com/9/c2/f0ee8a3c7c9638a54940382568c9dpng.png",
sizeList: ["large", "medium", "small"]
}
}
}
</script>
```
:::
### Types
It supports images, Icons, or characters
:::demo
```html
<template>
<div class="demo-type">
<div>
<el-avatar icon="el-icon-user-solid"></el-avatar>
</div>
<div>
<el-avatar src="https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png"></el-avatar>
</div>
<div>
<el-avatar> user </el-avatar>
</div>
</div>
</template>
```
:::
### Fallback when image load error
fallback when image load error
:::demo
```html
<template>
<div class="demo-type">
<el-avatar :size="60" src="https://empty" @error="errorHandler">
<img src="https://cube.elemecdn.com/e/fd/0fc7d20532fdaf769a25683617711png.png"/>
</el-avatar>
</div>
</template>
<script>
export default {
methods: {
errorHandler() {
return true
}
}
}
</script>
```
:::
### How the image fit its container
Set how the image fit its container for an image avatar, same as [object-fit](https://developer.mozilla.org/en-US/docs/Web/CSS/object-fit).
:::demo
```html
<template>
<div class="demo-fit">
<div class="block" v-for="fit in fits" :key="fit">
<span class="title">{{ fit }}</span>
<el-avatar shape="square" :size="100" :fit="fit" :src="url"></el-avatar>
</div>
</div>
</template>
<script>
export default {
data() {
return {
fits: ['fill', 'contain', 'cover', 'none', 'scale-down'],
url: 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg'
}
}
}
</script>
```
:::
### Attributes
| Attribute | Description | Type | Accepted Values | Default |
| ----------------- | -------------------------------- | --------------- | ------ | ------ |
| icon | set representation type to Icon, more info on Icon Component | string | | |
| size | set avatar size | number/string | number / large / medium / small | large |
| shape | set avatar shape | string | circle / square | circle |
| src | the address of the image for an image avatar | string | | |
| srcSet | A list of one or more strings separated by commas indicating a set of possible image sources for the user agent to use | string | | |
| alt | This attribute defines an alternative text description of the image | string | | |
| fit | set how the image fit its container for an image avatar | string | fill / contain / cover / none / scale-down | cover |
### Events
| Event Name | Description | Parameters |
| ------ | ------------------ | -------- |
| error | handler when img load error, return false to prevent default fallback behavior |(e: Event) |
### Slot
| Slot Name | Description |
| default | customize avatar content |

View File

@ -0,0 +1,145 @@
## Avatar avatar
Avatars can be used to represent people or objects. It supports images, Icons, or characters.
### Basic
use `shape` and `size` prop to set avatar's shape and size
:::demo
```html
<template>
<el-row class="demo-avatar demo-basic">
<el-col :span="12">
<div class="sub-title">circle</div>
<div class="demo-basic--circle">
<div class="block"><el-avatar :size="50" :src="circleUrl"></el-avatar></div>
<div class="block" v-for="size in sizeList" :key="size">
<el-avatar :size="size" :src="circleUrl"></el-avatar>
</div>
</div>
</el-col>
<el-col :span="12">
<div class="sub-title">square</div>
<div class="demo-basic--circle">
<div class="block"><el-avatar shape="square" :size="50" :src="squareUrl"></el-avatar></div>
<div class="block" v-for="size in sizeList" :key="size">
<el-avatar shape="square" :size="size" :src="squareUrl"></el-avatar>
</div>
</div>
</el-col>
</el-row>
</template>
<script>
export default {
data () {
return {
circleUrl: "https://cube.elemecdn.com/3/7c/3ea6beec64369c2642b92c6726f1epng.png",
squareUrl: "https://cube.elemecdn.com/9/c2/f0ee8a3c7c9638a54940382568c9dpng.png",
sizeList: ["large", "medium", "small"]
}
}
}
</script>
```
:::
### Types
It supports images, Icons, or characters
:::demo
```html
<template>
<div class="demo-type">
<div>
<el-avatar icon="el-icon-user-solid"></el-avatar>
</div>
<div>
<el-avatar src="https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png"></el-avatar>
</div>
<div>
<el-avatar> user </el-avatar>
</div>
</div>
</template>
```
:::
### Fallback when image load error
fallback when image load error
:::demo
```html
<template>
<div class="demo-type">
<el-avatar :size="60" src="https://empty" @error="errorHandler">
<img src="https://cube.elemecdn.com/e/fd/0fc7d20532fdaf769a25683617711png.png"/>
</el-avatar>
</div>
</template>
<script>
export default {
methods: {
errorHandler() {
return true
}
}
}
</script>
```
:::
### How the image fit its container
Set how the image fit its container for an image avatar, same as [object-fit](https://developer.mozilla.org/en-US/docs/Web/CSS/object-fit).
:::demo
```html
<template>
<div class="demo-fit">
<div class="block" v-for="fit in fits" :key="fit">
<span class="title">{{ fit }}</span>
<el-avatar shape="square" :size="100" :fit="fit" :src="url"></el-avatar>
</div>
</div>
</template>
<script>
export default {
data() {
return {
fits: ['fill', 'contain', 'cover', 'none', 'scale-down'],
url: 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg'
}
}
}
</script>
```
:::
### Attributes
| Attribute | Description | Type | Accepted Values | Default |
| ----------------- | -------------------------------- | --------------- | ------ | ------ |
| icon | set representation type to Icon, more info on Icon Component | string | | |
| size | set avatar size | number/string | number / large / medium / small | large |
| shape | set avatar shape | string | circle / square | circle |
| src | the address of the image for an image avatar | string | | |
| srcSet | A list of one or more strings separated by commas indicating a set of possible image sources for the user agent to use | string | | |
| alt | This attribute defines an alternative text description of the image | string | | |
| fit | set how the image fit its container for an image avatar | string | fill / contain / cover / none / scale-down | cover |
### Events
| Event Name | Description | Parameters |
| ------ | ------------------ | -------- |
| error | handler when img load error, return false to prevent default fallback behavior |(e: Event) |
### Slot
| Slot Name | Description |
| default | customize avatar content |

View File

@ -0,0 +1,147 @@
## Avatar 头像
用图标、图片或者字符的形式展示用户或事物信息。
### 基本用法
通过 `shape``size` 设置头像的形状和大小。
:::demo
```html
<template>
<el-row class="demo-avatar demo-basic">
<el-col :span="12">
<div class="sub-title">circle</div>
<div class="demo-basic--circle">
<div class="block"><el-avatar :size="50" :src="circleUrl"></el-avatar></div>
<div class="block" v-for="size in sizeList" :key="size">
<el-avatar :size="size" :src="circleUrl"></el-avatar>
</div>
</div>
</el-col>
<el-col :span="12">
<div class="sub-title">square</div>
<div class="demo-basic--circle">
<div class="block"><el-avatar shape="square" :size="50" :src="squareUrl"></el-avatar></div>
<div class="block" v-for="size in sizeList" :key="size">
<el-avatar shape="square" :size="size" :src="squareUrl"></el-avatar>
</div>
</div>
</el-col>
</el-row>
</template>
<script>
export default {
data () {
return {
circleUrl: "https://cube.elemecdn.com/3/7c/3ea6beec64369c2642b92c6726f1epng.png",
squareUrl: "https://cube.elemecdn.com/9/c2/f0ee8a3c7c9638a54940382568c9dpng.png",
sizeList: ["large", "medium", "small"]
}
}
}
</script>
```
:::
### 展示类型
支持三种类型:图标、图片和字符
:::demo
```html
<template>
<div class="demo-type">
<div>
<el-avatar icon="el-icon-user-solid"></el-avatar>
</div>
<div>
<el-avatar src="https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png"></el-avatar>
</div>
<div>
<el-avatar> user </el-avatar>
</div>
</div>
</template>
```
:::
### 图片加载失败的 fallback 行为
当展示类型为图片的时候,图片加载失败的 fallback 行为
:::demo
```html
<template>
<div class="demo-type">
<el-avatar :size="60" src="https://empty" @error="errorHandler">
<img src="https://cube.elemecdn.com/e/fd/0fc7d20532fdaf769a25683617711png.png"/>
</el-avatar>
</div>
</template>
<script>
export default {
methods: {
errorHandler() {
return true
}
}
}
</script>
```
:::
### 图片如何适应容器框
当展示类型为图片的时候,使用 `fit` 属性定义图片如何适应容器框,同原生 [object-fit](https://developer.mozilla.org/en-US/docs/Web/CSS/object-fit)。
:::demo
```html
<template>
<div class="demo-fit">
<div class="block" v-for="fit in fits" :key="fit">
<span class="title">{{ fit }}</span>
<el-avatar shape="square" :size="100" :fit="fit" :src="url"></el-avatar>
</div>
</div>
</template>
<script>
export default {
data() {
return {
fits: ['fill', 'contain', 'cover', 'none', 'scale-down'],
url: 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg'
}
}
}
</script>
```
:::
### Attributes
| 参数 | 说明 | 类型 | 可选值 | 默认值 |
| ----------------- | -------------------------------- | --------------- | ------ | ------ |
| icon | 设置头像的图标类型,参考 Icon 组件 | string | | |
| size | 设置头像的大小 | number/string | number / large / medium / small | large |
| shape | 设置头像的形状 | string | circle / square | circle |
| src | 图片头像的资源地址 | string | | |
| srcSet | 以逗号分隔的一个或多个字符串列表表明一系列用户代理使用的可能的图像 | string | | |
| alt | 描述图像的替换文本 | string | | |
| fit | 当展示类型为图片的时候,设置图片如何适应容器框 | string | fill / contain / cover / none / scale-down | cover |
### Events
| 事件名 | 说明 | 回调参数 |
| ------ | ------------------ | -------- |
| error | 图片类头像加载失败的回调, 返回 false 会关闭组件默认的 fallback 行为 |(e: Event) |
### Slot
| 名称 | 说明 |
| ------ | ------------------ |
| default | 自定义头像展示内容 |

View File

@ -172,6 +172,10 @@
{ {
"path": "/badge", "path": "/badge",
"title": "Badge 标记" "title": "Badge 标记"
},
{
"path": "/avatar",
"title": "Avatar 头像"
} }
] ]
}, },
@ -565,6 +569,10 @@
{ {
"path": "/infiniteScroll", "path": "/infiniteScroll",
"title": "InfiniteScroll" "title": "InfiniteScroll"
},
{
"path": "/avatar",
"title": "Avatar"
} }
] ]
} }
@ -851,6 +859,10 @@
{ {
"path": "/infiniteScroll", "path": "/infiniteScroll",
"title": "InfiniteScroll" "title": "InfiniteScroll"
},
{
"path": "/avatar",
"title": "Avatar"
} }
] ]
} }
@ -1137,6 +1149,10 @@
{ {
"path": "/infiniteScroll", "path": "/infiniteScroll",
"title": "InfiniteScroll" "title": "InfiniteScroll"
},
{
"path": "/avatar",
"title": "Avatar"
} }
] ]
} }

8
packages/avatar/index.js Normal file
View File

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

View File

@ -0,0 +1,107 @@
<script>
export default {
name: 'ElAvatar',
props: {
size: {
type: [Number, String],
validator(val) {
if (typeof val === 'string') {
return ['large', 'medium', 'small'].includes(val);
}
return typeof val === 'number';
}
},
shape: {
type: String,
default: 'circle',
validator(val) {
return ['circle', 'square'].includes(val);
}
},
icon: String,
src: String,
alt: String,
srcSet: String,
error: Function,
fit: {
type: String,
default: 'cover'
}
},
data() {
return {
isImageExist: true
};
},
computed: {
avatarClass() {
const { size, icon, shape } = this;
let classList = ['el-avatar'];
if (size && typeof size === 'string') {
classList.push(`el-avatar--${size}`);
}
if (icon) {
classList.push('el-avatar--icon');
}
if (shape) {
classList.push(`el-avatar--${shape}`);
}
return classList.join(' ');
}
},
methods: {
handleError() {
const { error } = this;
const errorFlag = error ? error() : undefined;
if (errorFlag !== false) {
this.isImageExist = false;
}
},
renderAvatar() {
const { icon, src, alt, isImageExist, srcSet, fit } = this;
if (isImageExist && src) {
return <img
src={src}
onError={this.handleError}
alt={alt}
srcSet={srcSet}
style={{ 'object-fit': fit }}/>;
}
if (icon) {
return (<i class={icon} />);
}
return this.$slots.default;
}
},
render() {
const { avatarClass, size } = this;
const sizeStyle = typeof size === 'number' ? {
height: `${size}px`,
width: `${size}px`,
lineHeight: `${size}px`
} : {};
return (
<span class={ avatarClass } style={ sizeStyle }>
{
this.renderAvatar()
}
</span>
);
}
};
</script>

View File

@ -0,0 +1,49 @@
@import "mixins/mixins";
@import "common/var";
@include b(avatar) {
display: inline-block;
box-sizing: border-box;
text-align: center;
overflow: hidden;
color: $--avatar-font-color;
background: $--avatar-background-color;
width: $--avatar-size;
height: $--avatar-size;
line-height: $--avatar-size;
>img {
width: 100%;
height: 100%;
}
@include m(circle) {
border-radius: 50%;
}
@include m(square) {
border-radius: 4px;
}
@include m(icon) {
font-size: 18px;
}
@include m(large) {
width: $--avatar-large-size;
height: $--avatar-large-size;
line-height: $--avatar-large-size;
}
@include m(medium) {
width: $--avatar-medium-size;
height: $--avatar-medium-size;
line-height: $--avatar-medium-size;
}
@include m(small) {
width: $--avatar-small-size;
height: $--avatar-small-size;
line-height: $--avatar-small-size;
}
}

View File

@ -939,6 +939,17 @@ $--calendar-border: $--table-border !default;
$--calendar-selected-background-color: #F2F8FE !default; $--calendar-selected-background-color: #F2F8FE !default;
$--calendar-cell-width: 85px !default; $--calendar-cell-width: 85px !default;
/* Avatar
--------------------------*/
/// color||Color|0
$--avatar-font-color: #fff;
/// color||Color|0
$--avatar-background-color: #C0C4CC;
$--avatar-size: 40px;
$--avatar-large-size: $--avatar-size;
$--avatar-medium-size: 36px;
$--avatar-small-size: 28px;
/* Break-point /* Break-point
--------------------------*/ --------------------------*/
$--sm: 768px !default; $--sm: 768px !default;

View File

@ -75,3 +75,4 @@
@import "./infinite-scroll.scss"; @import "./infinite-scroll.scss";
@import "./page-header.scss"; @import "./page-header.scss";
@import "./cascader-panel.scss"; @import "./cascader-panel.scss";
@import "./avatar.scss";

View File

@ -79,6 +79,7 @@ import Backtop from '../packages/backtop/index.js';
import InfiniteScroll from '../packages/infinite-scroll/index.js'; import InfiniteScroll from '../packages/infinite-scroll/index.js';
import PageHeader from '../packages/page-header/index.js'; import PageHeader from '../packages/page-header/index.js';
import CascaderPanel from '../packages/cascader-panel/index.js'; import CascaderPanel from '../packages/cascader-panel/index.js';
import Avatar from '../packages/avatar/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';
@ -157,6 +158,7 @@ const components = [
Backtop, Backtop,
PageHeader, PageHeader,
CascaderPanel, CascaderPanel,
Avatar,
CollapseTransition CollapseTransition
]; ];
@ -275,5 +277,6 @@ export default {
Backtop, Backtop,
InfiniteScroll, InfiniteScroll,
PageHeader, PageHeader,
CascaderPanel CascaderPanel,
Avatar
}; };

View File

@ -0,0 +1,123 @@
import {createTest, createVue, destroyVM} from '../util';
import Avatar from 'packages/avatar';
describe('Avatar', () => {
let vm;
afterEach(() => {
destroyVM(vm);
});
it('create', () => {
vm = createTest(Avatar);
expect(vm.$el).to.exist;
});
it('size is number', () => {
vm = createVue({
template: `
<el-avatar :size="50">
</el-avatar>
`
}, true);
const avatarElm = vm.$el;
expect(avatarElm.style.height).to.equal('50px');
});
it('size is string', () => {
vm = createVue({
template: `
<el-avatar size="small">
user
</el-avatar>
`
}, true);
const avatarElm = vm.$el;
expect(avatarElm.classList.contains('el-avatar--small')).to.be.true;
});
it('shape', () => {
vm = createVue({
template: `
<el-avatar size="small" shape="square">
user
</el-avatar>
`
}, true);
const avatarElm = vm.$el;
expect(avatarElm.classList.contains('el-avatar--square')).to.be.true;
});
it('icon avatar', () => {
vm = createVue({
template: `
<el-avatar icon="el-icon-user-solid">
</el-avatar>
`
}, true);
const avatarElm = vm.$el;
const iconELm = avatarElm.children[0];
expect(avatarElm.classList.contains('el-avatar--icon')).to.be.true;
expect(iconELm.classList.contains('el-icon-user-solid')).to.be.true;
});
it('image avatar', () => {
vm = createVue({
template: `
<el-avatar src="https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png"></el-avatar>
`
}, true);
const imgElm = vm.$el.children[0];
expect(imgElm.tagName.toUpperCase()).to.equal('IMG');
expect(imgElm.src).to.equal('https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png');
});
it('image fallback', (done) => {
vm = createVue({
template: `
<el-avatar src="https://empty" @error="errorHandler">
fallback
</el-avatar>
`,
methods: {
errorHandler() {
return true;
}
}
}, true);
setTimeout(() => {
const avatarElm = vm.$el;
expect(avatarElm.textContent.trim()).to.equal('fallback');
done();
}, 3000);
});
it('image fit', (done) => {
vm = createVue({
template: `
<div>
<el-avatar :src="url"></el-avatar>
<el-avatar :src="url" v-for="fit in fits" :fit="fit" :key="fit"></el-avatar>
</div>
`,
data() {
return {
fits: ['fill', 'contain', 'cover', 'none', 'scale-down'],
url: 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg'
};
}
}, true);
setTimeout(() => {
const containerElm = vm.$el;
expect(containerElm.children[0].children[0].style.objectFit).to.equal('cover');
expect(containerElm.children[1].children[0].style.objectFit).to.equal('fill');
expect(containerElm.children[2].children[0].style.objectFit).to.equal('contain');
expect(containerElm.children[3].children[0].style.objectFit).to.equal('cover');
expect(containerElm.children[4].children[0].style.objectFit).to.equal('none');
expect(containerElm.children[5].children[0].style.objectFit).to.equal('scale-down');
done();
}, 3000);
});
});

20
types/avatar.d.ts vendored Normal file
View File

@ -0,0 +1,20 @@
import { ElementUIComponent } from './component'
/** Avatar Component */
export declare class ElAvatar extends ElementUIComponent {
icon: string;
size: string | number;
shape: string;
src: string;
error: () => false;
srcSet: string;
alt: string;
fit: string;
}

View File

@ -77,6 +77,7 @@ import { ElImage } from './image'
import { ElBacktop } from './backtop' import { ElBacktop } from './backtop'
import { ElInfiniteScroll } from './infiniteScroll' import { ElInfiniteScroll } from './infiniteScroll'
import { ElPageHeader } from './page-header' import { ElPageHeader } from './page-header'
import { ElAvatar } from './avatar'
export interface InstallationOptions { export interface InstallationOptions {
locale: any, locale: any,
@ -332,3 +333,6 @@ export const InfiniteScroll: PluginObject<ElInfiniteScroll>;
/** PageHeader Component */ /** PageHeader Component */
export class PageHeader extends ElPageHeader {} export class PageHeader extends ElPageHeader {}
/** Avatar Component */
export class Avatar extends ElAvatar {}