mirror of
https://github.com/ant-design/ant-design.git
synced 2024-11-29 13:47:02 +08:00
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:
parent
0879bd5df3
commit
abebd55f0e
@ -23,7 +23,7 @@ const SkeletonAvatar = (props: AvatarProps) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
return <ConfigConsumer>{renderSkeletonAvatar}</ConfigConsumer>;
|
return <ConfigConsumer>{renderSkeletonAvatar}</ConfigConsumer>;
|
||||||
}
|
};
|
||||||
|
|
||||||
SkeletonAvatar.defaultProps = {
|
SkeletonAvatar.defaultProps = {
|
||||||
size: 'default',
|
size: 'default',
|
||||||
|
@ -27,11 +27,12 @@ const Element = (props: SkeletonElementProps) => {
|
|||||||
const sizeStyle: React.CSSProperties =
|
const sizeStyle: React.CSSProperties =
|
||||||
typeof size === 'number'
|
typeof size === 'number'
|
||||||
? {
|
? {
|
||||||
width: size,
|
width: size,
|
||||||
height: size,
|
height: size,
|
||||||
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;
|
||||||
|
35
components/skeleton/Image.tsx
Normal file
35
components/skeleton/Image.tsx
Normal 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;
|
@ -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;
|
||||||
|
@ -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>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
@ -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"
|
||||||
|
@ -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();
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@ -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>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
Loading…
Reference in New Issue
Block a user