Browse Source

Merge pull request #6415 from ddcat1115/Avatar

Avatar
pull/6388/head
偏右 8 years ago
committed by GitHub
parent
commit
053521be39
  1. 1
      components/__tests__/__snapshots__/index.test.js.snap
  2. 11
      components/avatar/__tests__/Avatar.test.js
  3. 389
      components/avatar/__tests__/__snapshots__/demo.test.js.snap
  4. 3
      components/avatar/__tests__/demo.test.js
  5. 29
      components/avatar/demo/badge.md
  6. 33
      components/avatar/demo/basic.md
  7. 49
      components/avatar/demo/dynamic.md
  8. 33
      components/avatar/demo/type.md
  9. 16
      components/avatar/index.en-US.md
  10. 120
      components/avatar/index.tsx
  11. 17
      components/avatar/index.zh-CN.md
  12. 47
      components/avatar/style/index.less
  13. 2
      components/avatar/style/index.tsx
  14. 2
      components/index.tsx
  15. 11
      components/style/themes/default.less
  16. 1
      tests/__snapshots__/index.test.js.snap

1
components/__tests__/__snapshots__/index.test.js.snap

@ -6,6 +6,7 @@ Array [
"Anchor",
"AutoComplete",
"Alert",
"Avatar",
"BackTop",
"Badge",
"Breadcrumb",

11
components/avatar/__tests__/Avatar.test.js

@ -0,0 +1,11 @@
import React from 'react';
import { mount } from 'enzyme';
import Avatar from '..';
describe('Avatar Render', () => {
it('Render long string correctly', () => {
const wrapper = mount(<Avatar>TestString</Avatar>);
const children = wrapper.find('.ant-avatar-string');
expect(children.length).toBe(1);
});
});

389
components/avatar/__tests__/__snapshots__/demo.test.js.snap

@ -0,0 +1,389 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`renders ./components/avatar/demo/badge.md correctly 1`] = `
<div>
<span
style="margin-right:24px;"
>
<span
class="ant-badge"
title="1"
>
<span
class="ant-avatar ant-avatar-square ant-avatar-icon"
>
<i
class="anticon anticon-user"
/>
</span>
<sup
class="ant-scroll-number ant-badge-count"
data-show="true"
>
<span
class="ant-scroll-number-only"
style="transition:none;-ms-transform:translateY(-1100%);-webkit-transform:translateY(-1100%);transform:translateY(-1100%);"
>
<p
class=""
>
0
</p>
<p
class=""
>
1
</p>
<p
class=""
>
2
</p>
<p
class=""
>
3
</p>
<p
class=""
>
4
</p>
<p
class=""
>
5
</p>
<p
class=""
>
6
</p>
<p
class=""
>
7
</p>
<p
class=""
>
8
</p>
<p
class=""
>
9
</p>
<p
class=""
>
0
</p>
<p
class="current"
>
1
</p>
<p
class=""
>
2
</p>
<p
class=""
>
3
</p>
<p
class=""
>
4
</p>
<p
class=""
>
5
</p>
<p
class=""
>
6
</p>
<p
class=""
>
7
</p>
<p
class=""
>
8
</p>
<p
class=""
>
9
</p>
<p
class=""
>
0
</p>
<p
class=""
>
1
</p>
<p
class=""
>
2
</p>
<p
class=""
>
3
</p>
<p
class=""
>
4
</p>
<p
class=""
>
5
</p>
<p
class=""
>
6
</p>
<p
class=""
>
7
</p>
<p
class=""
>
8
</p>
<p
class=""
>
9
</p>
</span>
</sup>
</span>
</span>
<span>
<span
class="ant-badge"
>
<span
class="ant-avatar ant-avatar-square ant-avatar-icon"
>
<i
class="anticon anticon-user"
/>
</span>
<sup
class="ant-scroll-number ant-badge-dot"
data-show="true"
/>
</span>
</span>
</div>
`;
exports[`renders ./components/avatar/demo/basic.md correctly 1`] = `
<div>
<div
class="ant-row"
>
<div
class="ant-col-4"
>
<span
class="ant-avatar ant-avatar-lg ant-avatar-circle ant-avatar-icon"
>
<i
class="anticon anticon-user"
/>
</span>
</div>
<div
class="ant-col-4"
>
<span
class="ant-avatar ant-avatar-circle ant-avatar-icon"
>
<i
class="anticon anticon-user"
/>
</span>
</div>
<div
class="ant-col-4"
>
<span
class="ant-avatar ant-avatar-sm ant-avatar-circle ant-avatar-icon"
>
<i
class="anticon anticon-user"
/>
</span>
</div>
</div>
<div
class="ant-row"
>
<div
class="ant-col-4"
>
<span
class="ant-avatar ant-avatar-lg ant-avatar-square ant-avatar-icon"
>
<i
class="anticon anticon-user"
/>
</span>
</div>
<div
class="ant-col-4"
>
<span
class="ant-avatar ant-avatar-square ant-avatar-icon"
>
<i
class="anticon anticon-user"
/>
</span>
</div>
<div
class="ant-col-4"
>
<span
class="ant-avatar ant-avatar-sm ant-avatar-square ant-avatar-icon"
>
<i
class="anticon anticon-user"
/>
</span>
</div>
</div>
</div>
`;
exports[`renders ./components/avatar/demo/dynamic.md correctly 1`] = `
<div>
<span
class="ant-avatar ant-avatar-lg ant-avatar-circle"
style="background-color:#f56a00;"
>
<span
class="ant-avatar-string"
>
U
</span>
</span>
<button
class="ant-btn ant-btn-sm"
style="margin-left:16px;"
type="button"
>
<span>
Change
</span>
</button>
</div>
`;
exports[`renders ./components/avatar/demo/type.md correctly 1`] = `
<div>
<div
class="ant-row"
>
<div
class="ant-col-4"
>
<span
class="ant-avatar ant-avatar-circle ant-avatar-icon"
>
<i
class="anticon anticon-user"
/>
</span>
</div>
<div
class="ant-col-4"
>
<span
class="ant-avatar ant-avatar-circle"
>
<span
class="ant-avatar-string"
>
U
</span>
</span>
</div>
<div
class="ant-col-4"
>
<span
class="ant-avatar ant-avatar-circle"
>
<span
class="ant-avatar-string"
>
USER
</span>
</span>
</div>
<div
class="ant-col-4"
>
<span
class="ant-avatar ant-avatar-circle ant-avatar-image"
>
<img
src="https://os.alipayobjects.com/rmsportal/mgesTPFxodmIwpi.png"
/>
</span>
</div>
</div>
<div
class="ant-row"
>
<div
class="ant-col-4"
>
<span
class="ant-avatar ant-avatar-circle"
style="color:#f56a00;background-color:#fde3cf;"
>
<span
class="ant-avatar-string"
>
U
</span>
</span>
</div>
<div
class="ant-col-4"
>
<span
class="ant-avatar ant-avatar-circle ant-avatar-icon"
style="background-color:#87d068;"
>
<i
class="anticon anticon-user"
/>
</span>
</div>
</div>
</div>
`;

3
components/avatar/__tests__/demo.test.js

@ -0,0 +1,3 @@
import demoTest from '../../../tests/shared/demoTest';
demoTest('avatar');

29
components/avatar/demo/badge.md

@ -0,0 +1,29 @@
---
order: 3
title:
zh-CN: 带徽标的头像
en-US: With Badge
---
## zh-CN
通常用于消息提示。
## en-US
Usually used for messages remind.
````jsx
import { Avatar, Badge } from 'antd';
ReactDOM.render(
<div>
<span style={{ marginRight: 24 }}>
<Badge count={1}><Avatar shape="square" icon="user" /></Badge>
</span>
<span>
<Badge dot><Avatar shape="square" icon="user" /></Badge>
</span>
</div>
, mountNode);
````

33
components/avatar/demo/basic.md

@ -0,0 +1,33 @@
---
order: 0
title:
zh-CN: 基本
en-US: Basic
---
## zh-CN
头像有三种尺寸,两种形状可选。
## en-US
Three sizes and two shapes are available.
````jsx
import { Avatar, Row, Col } from 'antd';
ReactDOM.render(
<div>
<Row>
<Col span={4}><Avatar size="large" icon="user" /></Col>
<Col span={4}><Avatar icon="user" /></Col>
<Col span={4}><Avatar size="small" icon="user" /></Col>
</Row>
<Row>
<Col span={4}><Avatar shape="square" size="large" icon="user" /></Col>
<Col span={4}><Avatar shape="square" icon="user" /></Col>
<Col span={4}><Avatar shape="square" size="small" icon="user" /></Col>
</Row>
</div>
, mountNode);
````

49
components/avatar/demo/dynamic.md

@ -0,0 +1,49 @@
---
order: 2
title:
zh-CN: 自动调整字符大小
en-US: Autoset Font Size
---
## zh-CN
对于字符型的头像,当字符串较长时,字体大小可以根据头像宽度自动调整。
## en-US
For letter type Avatar, when the letters are too long to display, the font size can be automatically adjusted according to the width of the Avatar.
````jsx
import { Avatar, Button } from 'antd';
const UserList = ['U', 'Lucy', 'Tom', 'Edward'];
const colorList = ['#f56a00', '#7265e6', '#ffbf00', '#00a2ae'];
class Autoset extends React.Component {
constructor(props) {
super(props);
this.state = {
user: UserList[0],
color: colorList[0],
};
}
changeUser = () => {
const index = UserList.indexOf(this.state.user);
this.setState({
user: index < UserList.length - 1 ? UserList[index + 1] : UserList[0],
color: index < colorList.length - 1 ? colorList[index + 1] : colorList[0],
});
}
render() {
return (
<div>
<Avatar style={{ backgroundColor: this.state.color }} size="large">{this.state.user}</Avatar>
<Button size="small" style={{ marginLeft: 16 }} onClick={this.changeUser}>Change</Button>
</div>
);
}
}
ReactDOM.render(<Autoset />
, mountNode);
````

33
components/avatar/demo/type.md

@ -0,0 +1,33 @@
---
order: 1
title:
zh-CN: 类型
en-US: Type
---
## zh-CN
支持三种类型:图片、Icon 以及字符,其中 Icon 和字符型可以自定义图标颜色及背景色。
## en-US
Image, Icon and letter are supported, and the latter two kinds avatar can have custom colors and background colors.
````jsx
import { Avatar, Row, Col } from 'antd';
ReactDOM.render(
<div>
<Row>
<Col span={4}><Avatar icon="user" /></Col>
<Col span={4}><Avatar>U</Avatar></Col>
<Col span={4}><Avatar>USER</Avatar></Col>
<Col span={4}><Avatar src="https://os.alipayobjects.com/rmsportal/mgesTPFxodmIwpi.png" /></Col>
</Row>
<Row>
<Col span={4}><Avatar style={{ color: '#f56a00', backgroundColor: '#fde3cf' }}>U</Avatar></Col>
<Col span={4}><Avatar style={{ backgroundColor: '#87d068' }} icon="user" /></Col>
</Row>
</div>
, mountNode);
````

16
components/avatar/index.en-US.md

@ -0,0 +1,16 @@
---
category: Components
type: Data Display
title: Avatar
---
Avatars can be used to represent people or object, which supports image, antd-Icon, or letter.
## API
| Property | Description | Type | Default |
|----------- |--------------------------------------------------------- | ---------- |-------|
| type | to set the shape of avatar | Enum{ 'circle', 'square' } | `circle` |
| size | to set the size of avatar | Enum{ 'large', 'small', 'default' } | `default` |
| src | the address of a image avatar | string | - |
| icon | the icon type of a icon avatar, see `Icon` Component | string | - |

120
components/avatar/index.tsx

@ -0,0 +1,120 @@
import React from 'react';
import ReactDOM from 'react-dom';
import Icon from '../icon';
import classNames from 'classnames';
export interface AvatarProps {
/** Shape of avatar, options:`circle`, `square` */
shape?: 'circle' | 'square';
/** Size of avatar, options:`large`, `small`, `default` */
size?: 'large' | 'small' | 'default';
/** Src of image avatar */
src?: string;
/** Type of the Icon to be used in avatar */
icon?: string;
style?: React.CSSProperties;
prefixCls?: string;
className?: string;
children?: any;
}
export default class Avatar extends React.Component<AvatarProps, any> {
static defaultProps = {
prefixCls: 'ant-avatar',
shape: 'circle',
size: 'default',
};
private avatarChildren: any;
constructor(props) {
super(props);
this.state = {
scale: 1,
};
}
componentDidMount() {
this.setScale();
}
componentDidUpdate(prevProps, prevState) {
if (prevProps.children !== this.props.children
|| (prevState.scale !== this.state.scale && this.state.scale === 1)) {
this.setScale();
}
}
setScale = () => {
const childrenNode = this.avatarChildren;
if (childrenNode) {
const childrenWidth = childrenNode.offsetWidth;
const avatarWidth = ReactDOM.findDOMNode(this).getBoundingClientRect().width;
// add 4px gap for each side to get better performance
if (avatarWidth - 8 < childrenWidth) {
this.setState({
scale: (avatarWidth - 8) / childrenWidth,
});
} else {
this.setState({
scale: 1,
});
}
}
}
render() {
const {
prefixCls, shape, size, src, icon, className, ...others,
} = this.props;
const sizeCls = classNames({
[`${prefixCls}-lg`]: size === 'large',
[`${prefixCls}-sm`]: size === 'small',
});
const classString = classNames(prefixCls, className, sizeCls, {
[`${prefixCls}-${shape}`]: shape,
[`${prefixCls}-image`]: src,
[`${prefixCls}-icon`]: icon,
});
let children = this.props.children;
if (src) {
children = <img src={src} />;
} else if (icon) {
children = <Icon type={icon} />;
} else {
const childrenNode = this.avatarChildren;
if (childrenNode || this.state.scale !== 1) {
const childrenStyle: React.CSSProperties = {
msTransform: `scale(${this.state.scale})`,
WebkitTransform: `scale(${this.state.scale})`,
transform: `scale(${this.state.scale})`,
position: 'absolute',
display: 'inline-block',
left: `calc(50% - ${Math.round(childrenNode.offsetWidth / 2)}px)`,
};
children = <span
className={`${prefixCls}-string`}
ref={span => this.avatarChildren = span}
style={childrenStyle}
>
{children}
</span>;
} else {
children = <span
className={`${prefixCls}-string`}
ref={span => this.avatarChildren = span}
>
{children}
</span>;
}
}
return (
<span {...others} className={classString}>
{children}
</span>
);
}
}

17
components/avatar/index.zh-CN.md

@ -0,0 +1,17 @@
---
category: Components
subtitle: 头像
type: Data Display
title: Avatar
---
用来代表用户或事物,支持图片、图标或字符展示。
## API
| 参数 | 说明 | 类型 | 默认值 |
|----------- |--------------------------------------------------------- | ---------- | ------- |
| shape | 指定头像的形状 | Enum{ 'circle', 'square' } | `circle` |
| size | 设置头像的大小 | Enum{ 'large', 'small', 'default' } | `default` |
| src | 图片类头像的资源地址 | string | - |
| icon | 设置头像的图标类型,参考 `Icon` 组件 | string | - |

47
components/avatar/style/index.less

@ -0,0 +1,47 @@
@import "../../style/themes/default";
@avatar-prefix-cls: ~"@{ant-prefix}-avatar";
.@{avatar-prefix-cls} {
display: inline-block;
text-align: center;
background: @avatar-bg;
color: @avatar-color;
white-space: nowrap;
position: relative;
overflow: hidden;
.avatar-size(@avatar-size-base, @avatar-font-size-base);
&-lg {
.avatar-size(@avatar-size-lg, @avatar-font-size-lg);
}
&-sm {
.avatar-size(@avatar-size-sm, @avatar-font-size-sm);
}
&-square {
border-radius: @avatar-border-radius;
}
& > img {
width: 100%;
height: 100%;
}
}
.avatar-size(@size, @font-size) {
width: @size;
height: @size;
line-height: @size;
border-radius: @size / 2;
& > * {
line-height: @size;
}
&.@{avatar-prefix-cls}-icon {
font-size: @font-size;
}
}

2
components/avatar/style/index.tsx

@ -0,0 +1,2 @@
import '../../style/index.less';
import './index.less';

2
components/index.tsx

@ -19,6 +19,8 @@ export { default as AutoComplete } from './auto-complete';
export { default as Alert } from './alert';
export { default as Avatar } from './avatar';
export { default as BackTop } from './back-top';
export { default as Badge } from './badge';

11
components/style/themes/default.less

@ -335,3 +335,14 @@
@back-top-color: #fff;
@back-top-bg: rgba(64, 64, 64, 0.4);
@back-top-hover-bg: rgba(64, 64, 64, 0.6);
// Avatar
@avatar-size-base: 32px;
@avatar-size-lg: 40px;
@avatar-size-sm: 24px;
@avatar-font-size-base: 18px;
@avatar-font-size-lg: 24px;
@avatar-font-size-sm: 14px;
@avatar-bg: #ccc;
@avatar-color: #fff;
@avatar-border-radius: @border-radius-base;

1
tests/__snapshots__/index.test.js.snap

@ -6,6 +6,7 @@ Array [
"Anchor",
"AutoComplete",
"Alert",
"Avatar",
"BackTop",
"Badge",
"Breadcrumb",

Loading…
Cancel
Save