feat: add Skeleton-Image (#24805)

* feat: add Skeleton-Image

* feat: add docs

* fix: adjust skeleton

* feat: adjust Image Component

* feat: rebase

* feat: adjust style

* fix: lint

* feat: remove size

* feat: delete md

* feat: fix style
This commit is contained in:
zoomdong 2020-06-12 22:44:32 +08:00 committed by GitHub
parent 0879bd5df3
commit abebd55f0e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 154 additions and 13 deletions

View File

@ -23,7 +23,7 @@ const SkeletonAvatar = (props: AvatarProps) => {
); );
}; };
return <ConfigConsumer>{renderSkeletonAvatar}</ConfigConsumer>; return <ConfigConsumer>{renderSkeletonAvatar}</ConfigConsumer>;
} };
SkeletonAvatar.defaultProps = { SkeletonAvatar.defaultProps = {
size: 'default', size: 'default',

View File

@ -32,6 +32,7 @@ const Element = (props: SkeletonElementProps) => {
lineHeight: `${size}px`, lineHeight: `${size}px`,
} }
: {}; : {};
return ( return (
<span <span
className={classNames(prefixCls, className, sizeCls, shapeCls)} className={classNames(prefixCls, className, sizeCls, shapeCls)}
@ -40,5 +41,4 @@ const Element = (props: SkeletonElementProps) => {
); );
}; };
export default Element; export default Element;

View File

@ -0,0 +1,35 @@
import * as React from 'react';
import classNames from 'classnames';
import { SkeletonElementProps } from './Element';
import { ConfigConsumer, ConfigConsumerProps } from '../config-provider';
export interface SkeletonImageProps
extends Omit<SkeletonElementProps, 'size' | 'shape' | 'active'> {}
const path =
'M365.714286 329.142857q0 45.714286-32.036571 77.677714t-77.677714 32.036571-77.677714-32.036571-32.036571-77.677714 32.036571-77.677714 77.677714-32.036571 77.677714 32.036571 32.036571 77.677714zM950.857143 548.571429l0 256-804.571429 0 0-109.714286 182.857143-182.857143 91.428571 91.428571 292.571429-292.571429zM1005.714286 146.285714l-914.285714 0q-7.460571 0-12.873143 5.412571t-5.412571 12.873143l0 694.857143q0 7.460571 5.412571 12.873143t12.873143 5.412571l914.285714 0q7.460571 0 12.873143-5.412571t5.412571-12.873143l0-694.857143q0-7.460571-5.412571-12.873143t-12.873143-5.412571zM1097.142857 164.571429l0 694.857143q0 37.741714-26.843429 64.585143t-64.585143 26.843429l-914.285714 0q-37.741714 0-64.585143-26.843429t-26.843429-64.585143l0-694.857143q0-37.741714 26.843429-64.585143t64.585143-26.843429l914.285714 0q37.741714 0 64.585143 26.843429t26.843429 64.585143z';
const SkeletonImage = (props: SkeletonImageProps) => {
const renderSkeletonImage = ({ getPrefixCls }: ConfigConsumerProps) => {
const { prefixCls: customizePrefixCls, className, style } = props;
const prefixCls = getPrefixCls('skeleton', customizePrefixCls);
const cls = classNames(prefixCls, className, `${prefixCls}-element`);
return (
<div className={cls}>
<div className={classNames(`${prefixCls}-image`, className)} style={style}>
<svg
viewBox="0 0 1098 1024"
xmlns="http://www.w3.org/2000/svg"
className={`${prefixCls}-image-svg`}
>
<path d={path} className={`${prefixCls}-image-path`} />
</svg>
</div>
</div>
);
};
return <ConfigConsumer>{renderSkeletonImage}</ConfigConsumer>;
};
export default SkeletonImage;

View File

@ -7,10 +7,10 @@ import Element from './Element';
import SkeletonAvatar, { AvatarProps } from './Avatar'; import SkeletonAvatar, { AvatarProps } from './Avatar';
import SkeletonButton from './Button'; import SkeletonButton from './Button';
import SkeletonInput from './Input'; import SkeletonInput from './Input';
import SkeletonImage from './Image';
/* This only for skeleton internal. */ /* This only for skeleton internal. */
interface SkeletonAvatarProps extends Omit<AvatarProps, 'active'> { interface SkeletonAvatarProps extends Omit<AvatarProps, 'active'> {}
}
export interface SkeletonProps { export interface SkeletonProps {
active?: boolean; active?: boolean;
@ -170,5 +170,6 @@ Skeleton.defaultProps = {
Skeleton.Button = SkeletonButton; Skeleton.Button = SkeletonButton;
Skeleton.Avatar = SkeletonAvatar; Skeleton.Avatar = SkeletonAvatar;
Skeleton.Input = SkeletonInput; Skeleton.Input = SkeletonInput;
Skeleton.Image = SkeletonImage;
export default Skeleton; export default Skeleton;

View File

@ -686,6 +686,27 @@ exports[`renders ./components/skeleton/demo/element.md correctly 1`] = `
/> />
</div> </div>
</div> </div>
<br />
<div>
<div
class="ant-skeleton ant-skeleton-element"
>
<div
class="ant-skeleton-image"
>
<svg
class="ant-skeleton-image-svg"
viewBox="0 0 1098 1024"
xmlns="http://www.w3.org/2000/svg"
>
<path
class="ant-skeleton-image-path"
d="M365.714286 329.142857q0 45.714286-32.036571 77.677714t-77.677714 32.036571-77.677714-32.036571-32.036571-77.677714 32.036571-77.677714 77.677714-32.036571 77.677714 32.036571 32.036571 77.677714zM950.857143 548.571429l0 256-804.571429 0 0-109.714286 182.857143-182.857143 91.428571 91.428571 292.571429-292.571429zM1005.714286 146.285714l-914.285714 0q-7.460571 0-12.873143 5.412571t-5.412571 12.873143l0 694.857143q0 7.460571 5.412571 12.873143t12.873143 5.412571l914.285714 0q7.460571 0 12.873143-5.412571t5.412571-12.873143l0-694.857143q0-7.460571-5.412571-12.873143t-12.873143-5.412571zM1097.142857 164.571429l0 694.857143q0 37.741714-26.843429 64.585143t-64.585143 26.843429l-914.285714 0q-37.741714 0-64.585143-26.843429t-26.843429-64.585143l0-694.857143q0-37.741714 26.843429-64.585143t64.585143-26.843429l914.285714 0q37.741714 0 64.585143 26.843429t26.843429 64.585143z"
/>
</svg>
</div>
</div>
</div>
</div> </div>
`; `;

View File

@ -310,6 +310,27 @@ exports[`Skeleton button element size 3`] = `
</div> </div>
`; `;
exports[`Skeleton image element should render normal 1`] = `
<div
class="ant-skeleton ant-skeleton-element"
>
<div
class="ant-skeleton-image"
>
<svg
class="ant-skeleton-image-svg"
viewBox="0 0 1098 1024"
xmlns="http://www.w3.org/2000/svg"
>
<path
class="ant-skeleton-image-path"
d="M365.714286 329.142857q0 45.714286-32.036571 77.677714t-77.677714 32.036571-77.677714-32.036571-32.036571-77.677714 32.036571-77.677714 77.677714-32.036571 77.677714 32.036571 32.036571 77.677714zM950.857143 548.571429l0 256-804.571429 0 0-109.714286 182.857143-182.857143 91.428571 91.428571 292.571429-292.571429zM1005.714286 146.285714l-914.285714 0q-7.460571 0-12.873143 5.412571t-5.412571 12.873143l0 694.857143q0 7.460571 5.412571 12.873143t12.873143 5.412571l914.285714 0q7.460571 0 12.873143-5.412571t5.412571-12.873143l0-694.857143q0-7.460571-5.412571-12.873143t-12.873143-5.412571zM1097.142857 164.571429l0 694.857143q0 37.741714-26.843429 64.585143t-64.585143 26.843429l-914.285714 0q-37.741714 0-64.585143-26.843429t-26.843429-64.585143l0-694.857143q0-37.741714 26.843429-64.585143t64.585143-26.843429l914.285714 0q37.741714 0 64.585143 26.843429t26.843429 64.585143z"
/>
</svg>
</div>
</div>
`;
exports[`Skeleton input element active 1`] = ` exports[`Skeleton input element active 1`] = `
<div <div
class="ant-skeleton ant-skeleton-element ant-skeleton-active" class="ant-skeleton ant-skeleton-element ant-skeleton-active"

View File

@ -14,6 +14,7 @@ describe('Skeleton', () => {
const genSkeletonButton = props => mount(<Skeleton.Button {...props} />); const genSkeletonButton = props => mount(<Skeleton.Button {...props} />);
const genSkeletonAvatar = props => mount(<Skeleton.Avatar {...props} />); const genSkeletonAvatar = props => mount(<Skeleton.Avatar {...props} />);
const genSkeletonInput = props => mount(<Skeleton.Input {...props} />); const genSkeletonInput = props => mount(<Skeleton.Input {...props} />);
const genSkeletonImage = props => mount(<Skeleton.Image {...props} />);
mountTest(Skeleton); mountTest(Skeleton);
rtlTest(Skeleton); rtlTest(Skeleton);
@ -31,7 +32,7 @@ describe('Skeleton', () => {
it('should round title and paragraph', () => { it('should round title and paragraph', () => {
const wrapperSmall = genSkeleton({ round: true, title: true, paragraph: true }); const wrapperSmall = genSkeleton({ round: true, title: true, paragraph: true });
expect(wrapperSmall.render()).toMatchSnapshot(); expect(wrapperSmall.render()).toMatchSnapshot();
}) });
describe('avatar', () => { describe('avatar', () => {
it('size', () => { it('size', () => {
@ -135,4 +136,11 @@ describe('Skeleton', () => {
expect(wrapperLarge.render()).toMatchSnapshot(); expect(wrapperLarge.render()).toMatchSnapshot();
}); });
}); });
describe('image element', () => {
it('should render normal', () => {
const wrapper = genSkeletonImage();
expect(wrapper.render()).toMatchSnapshot();
});
});
}); });

View File

@ -1,17 +1,17 @@
--- ---
order: 2 order: 2
title: title:
zh-CN: 骨架按钮、头像和输入框 zh-CN: 骨架按钮、头像、输入框和图像
en-US: Skeleton button, avatar and input. en-US: Skeleton button, avatar, input and Image.
--- ---
## zh-CN ## zh-CN
骨架按钮、头像和输入框 骨架按钮、头像、输入框和图像
## en-US ## en-US
Skeleton button, avatar and input. Skeleton button, avatar, input and Image.
```jsx ```jsx
import { Skeleton, Switch, Form, Radio } from 'antd'; import { Skeleton, Switch, Form, Radio } from 'antd';
@ -113,6 +113,10 @@ class Demo extends React.Component {
</Form> </Form>
<Skeleton.Input style={{ width: '300px' }} active={inputActive} size={inputSize} /> <Skeleton.Input style={{ width: '300px' }} active={inputActive} size={inputSize} />
</div> </div>
<br />
<div>
<Skeleton.Image />
</div>
</div> </div>
); );
} }

View File

@ -7,6 +7,7 @@
@skeleton-paragraph-prefix-cls: ~'@{skeleton-prefix-cls}-paragraph'; @skeleton-paragraph-prefix-cls: ~'@{skeleton-prefix-cls}-paragraph';
@skeleton-button-prefix-cls: ~'@{skeleton-prefix-cls}-button'; @skeleton-button-prefix-cls: ~'@{skeleton-prefix-cls}-button';
@skeleton-input-prefix-cls: ~'@{skeleton-prefix-cls}-input'; @skeleton-input-prefix-cls: ~'@{skeleton-prefix-cls}-input';
@skeleton-image-prefix-cls: ~'@{skeleton-prefix-cls}-image';
.@{skeleton-prefix-cls} { .@{skeleton-prefix-cls} {
display: table; display: table;
@ -99,6 +100,10 @@
.@{skeleton-input-prefix-cls} { .@{skeleton-input-prefix-cls} {
.skeleton-color(); .skeleton-color();
} }
.@{skeleton-image-prefix-cls} {
.skeleton-color();
}
} }
// Skeleton element // Skeleton element
@ -115,6 +120,10 @@
.@{skeleton-input-prefix-cls} { .@{skeleton-input-prefix-cls} {
.skeleton-element-input(); .skeleton-element-input();
} }
.@{skeleton-image-prefix-cls} {
.skeleton-element-image();
}
} }
} }
// Button // Button
@ -168,6 +177,27 @@
} }
} }
// Image
.skeleton-element-image() {
display: flex;
align-items: center;
justify-content: center;
vertical-align: top;
background: @skeleton-color;
.skeleton-element-image-size(@image-size-base*2);
&-path {
fill: #bfbfbf;
}
&-svg {
.skeleton-element-image-size(@image-size-base);
max-width: @image-size-base * 4;
max-height: @image-size-base * 4;
}
}
.skeleton-element-avatar-size(@size) { .skeleton-element-avatar-size(@size) {
width: @size; width: @size;
.skeleton-element-common-size(@size); .skeleton-element-common-size(@size);
@ -196,6 +226,15 @@
.skeleton-element-common-size(@size); .skeleton-element-common-size(@size);
} }
.skeleton-element-image-size(@size) {
width: @size;
.skeleton-element-common-size(@size);
&.@{skeleton-image-prefix-cls}-circle {
border-radius: 50%;
}
}
.skeleton-element-common-size(@size) { .skeleton-element-common-size(@size) {
height: @size; height: @size;
line-height: @size; line-height: @size;

View File

@ -290,3 +290,8 @@
// Progress // Progress
// --- // ---
@progress-circle-text-font-size: 0.833333em; @progress-circle-text-font-size: 0.833333em;
// Image
// ---
@image-size-base: 48px;
@image-font-size-base: 24px;

View File

@ -964,3 +964,10 @@
@result-subtitle-font-size: @font-size-base; @result-subtitle-font-size: @font-size-base;
@result-icon-font-size: 72px; @result-icon-font-size: 72px;
@result-extra-margin: 24px 0 0 0; @result-extra-margin: 24px 0 0 0;
// Image
// ---
@image-size-base: 48px;
@image-font-size-base: 24px;
@image-bg: #ccc;
@image-color: #fff;