mirror of
https://github.com/ant-design/ant-design.git
synced 2024-11-26 04:00:13 +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>;
|
||||
}
|
||||
};
|
||||
|
||||
SkeletonAvatar.defaultProps = {
|
||||
size: 'default',
|
||||
|
@ -27,11 +27,12 @@ const Element = (props: SkeletonElementProps) => {
|
||||
const sizeStyle: React.CSSProperties =
|
||||
typeof size === 'number'
|
||||
? {
|
||||
width: size,
|
||||
height: size,
|
||||
lineHeight: `${size}px`,
|
||||
}
|
||||
width: size,
|
||||
height: size,
|
||||
lineHeight: `${size}px`,
|
||||
}
|
||||
: {};
|
||||
|
||||
return (
|
||||
<span
|
||||
className={classNames(prefixCls, className, sizeCls, shapeCls)}
|
||||
@ -40,5 +41,4 @@ const Element = (props: SkeletonElementProps) => {
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
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 SkeletonButton from './Button';
|
||||
import SkeletonInput from './Input';
|
||||
import SkeletonImage from './Image';
|
||||
|
||||
/* This only for skeleton internal. */
|
||||
interface SkeletonAvatarProps extends Omit<AvatarProps, 'active'> {
|
||||
}
|
||||
interface SkeletonAvatarProps extends Omit<AvatarProps, 'active'> {}
|
||||
|
||||
export interface SkeletonProps {
|
||||
active?: boolean;
|
||||
@ -170,5 +170,6 @@ Skeleton.defaultProps = {
|
||||
Skeleton.Button = SkeletonButton;
|
||||
Skeleton.Avatar = SkeletonAvatar;
|
||||
Skeleton.Input = SkeletonInput;
|
||||
Skeleton.Image = SkeletonImage;
|
||||
|
||||
export default Skeleton;
|
||||
|
@ -686,6 +686,27 @@ exports[`renders ./components/skeleton/demo/element.md correctly 1`] = `
|
||||
/>
|
||||
</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>
|
||||
`;
|
||||
|
||||
|
@ -310,6 +310,27 @@ exports[`Skeleton button element size 3`] = `
|
||||
</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`] = `
|
||||
<div
|
||||
class="ant-skeleton ant-skeleton-element ant-skeleton-active"
|
||||
|
@ -14,6 +14,7 @@ describe('Skeleton', () => {
|
||||
const genSkeletonButton = props => mount(<Skeleton.Button {...props} />);
|
||||
const genSkeletonAvatar = props => mount(<Skeleton.Avatar {...props} />);
|
||||
const genSkeletonInput = props => mount(<Skeleton.Input {...props} />);
|
||||
const genSkeletonImage = props => mount(<Skeleton.Image {...props} />);
|
||||
|
||||
mountTest(Skeleton);
|
||||
rtlTest(Skeleton);
|
||||
@ -31,7 +32,7 @@ describe('Skeleton', () => {
|
||||
it('should round title and paragraph', () => {
|
||||
const wrapperSmall = genSkeleton({ round: true, title: true, paragraph: true });
|
||||
expect(wrapperSmall.render()).toMatchSnapshot();
|
||||
})
|
||||
});
|
||||
|
||||
describe('avatar', () => {
|
||||
it('size', () => {
|
||||
@ -135,4 +136,11 @@ describe('Skeleton', () => {
|
||||
expect(wrapperLarge.render()).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
||||
describe('image element', () => {
|
||||
it('should render normal', () => {
|
||||
const wrapper = genSkeletonImage();
|
||||
expect(wrapper.render()).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -1,17 +1,17 @@
|
||||
---
|
||||
order: 2
|
||||
title:
|
||||
zh-CN: 骨架按钮、头像和输入框。
|
||||
en-US: Skeleton button, avatar and input.
|
||||
zh-CN: 骨架按钮、头像、输入框和图像。
|
||||
en-US: Skeleton button, avatar, input and Image.
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
骨架按钮、头像和输入框。
|
||||
骨架按钮、头像、输入框和图像。
|
||||
|
||||
## en-US
|
||||
|
||||
Skeleton button, avatar and input.
|
||||
Skeleton button, avatar, input and Image.
|
||||
|
||||
```jsx
|
||||
import { Skeleton, Switch, Form, Radio } from 'antd';
|
||||
@ -113,6 +113,10 @@ class Demo extends React.Component {
|
||||
</Form>
|
||||
<Skeleton.Input style={{ width: '300px' }} active={inputActive} size={inputSize} />
|
||||
</div>
|
||||
<br />
|
||||
<div>
|
||||
<Skeleton.Image />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -7,6 +7,7 @@
|
||||
@skeleton-paragraph-prefix-cls: ~'@{skeleton-prefix-cls}-paragraph';
|
||||
@skeleton-button-prefix-cls: ~'@{skeleton-prefix-cls}-button';
|
||||
@skeleton-input-prefix-cls: ~'@{skeleton-prefix-cls}-input';
|
||||
@skeleton-image-prefix-cls: ~'@{skeleton-prefix-cls}-image';
|
||||
|
||||
.@{skeleton-prefix-cls} {
|
||||
display: table;
|
||||
@ -99,6 +100,10 @@
|
||||
.@{skeleton-input-prefix-cls} {
|
||||
.skeleton-color();
|
||||
}
|
||||
|
||||
.@{skeleton-image-prefix-cls} {
|
||||
.skeleton-color();
|
||||
}
|
||||
}
|
||||
|
||||
// Skeleton element
|
||||
@ -115,6 +120,10 @@
|
||||
.@{skeleton-input-prefix-cls} {
|
||||
.skeleton-element-input();
|
||||
}
|
||||
|
||||
.@{skeleton-image-prefix-cls} {
|
||||
.skeleton-element-image();
|
||||
}
|
||||
}
|
||||
}
|
||||
// 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) {
|
||||
width: @size;
|
||||
.skeleton-element-common-size(@size);
|
||||
@ -196,6 +226,15 @@
|
||||
.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) {
|
||||
height: @size;
|
||||
line-height: @size;
|
||||
|
@ -290,3 +290,8 @@
|
||||
// Progress
|
||||
// ---
|
||||
@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-icon-font-size: 72px;
|
||||
@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