refactor: skeleton (#6224)
* refactor: skeleton * refactor: skeleton style * chore: modify skeleton demo stylepull/6227/head
parent
158cca7f8a
commit
dd57d1e305
|
@ -4,6 +4,7 @@ import classNames from '../_util/classNames';
|
||||||
import initDefaultProps from '../_util/props-util/initDefaultProps';
|
import initDefaultProps from '../_util/props-util/initDefaultProps';
|
||||||
import useConfigInject from '../config-provider/hooks/useConfigInject';
|
import useConfigInject from '../config-provider/hooks/useConfigInject';
|
||||||
import Element, { skeletonElementProps } from './Element';
|
import Element, { skeletonElementProps } from './Element';
|
||||||
|
import useStyle from './style';
|
||||||
|
|
||||||
export const avatarProps = () => {
|
export const avatarProps = () => {
|
||||||
return {
|
return {
|
||||||
|
@ -23,16 +24,22 @@ const SkeletonAvatar = defineComponent({
|
||||||
}),
|
}),
|
||||||
setup(props) {
|
setup(props) {
|
||||||
const { prefixCls } = useConfigInject('skeleton', props);
|
const { prefixCls } = useConfigInject('skeleton', props);
|
||||||
|
const [wrapSSR, hashId] = useStyle(prefixCls);
|
||||||
const cls = computed(() =>
|
const cls = computed(() =>
|
||||||
classNames(prefixCls.value, `${prefixCls.value}-element`, {
|
classNames(
|
||||||
[`${prefixCls.value}-active`]: props.active,
|
prefixCls.value,
|
||||||
}),
|
`${prefixCls.value}-element`,
|
||||||
|
{
|
||||||
|
[`${prefixCls.value}-active`]: props.active,
|
||||||
|
},
|
||||||
|
hashId.value,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
return () => {
|
return () => {
|
||||||
return (
|
return wrapSSR(
|
||||||
<div class={cls.value}>
|
<div class={cls.value}>
|
||||||
<Element {...props} prefixCls={`${prefixCls.value}-avatar`} />
|
<Element {...props} prefixCls={`${prefixCls.value}-avatar`} />
|
||||||
</div>
|
</div>,
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
|
@ -4,6 +4,7 @@ import classNames from '../_util/classNames';
|
||||||
import useConfigInject from '../config-provider/hooks/useConfigInject';
|
import useConfigInject from '../config-provider/hooks/useConfigInject';
|
||||||
import { initDefaultProps } from '../_util/props-util';
|
import { initDefaultProps } from '../_util/props-util';
|
||||||
import Element, { skeletonElementProps } from './Element';
|
import Element, { skeletonElementProps } from './Element';
|
||||||
|
import useStyle from './style';
|
||||||
|
|
||||||
export const skeletonButtonProps = () => {
|
export const skeletonButtonProps = () => {
|
||||||
return {
|
return {
|
||||||
|
@ -23,17 +24,23 @@ const SkeletonButton = defineComponent({
|
||||||
}),
|
}),
|
||||||
setup(props) {
|
setup(props) {
|
||||||
const { prefixCls } = useConfigInject('skeleton', props);
|
const { prefixCls } = useConfigInject('skeleton', props);
|
||||||
|
const [wrapSSR, hashId] = useStyle(prefixCls);
|
||||||
const cls = computed(() =>
|
const cls = computed(() =>
|
||||||
classNames(prefixCls.value, `${prefixCls.value}-element`, {
|
classNames(
|
||||||
[`${prefixCls.value}-active`]: props.active,
|
prefixCls.value,
|
||||||
[`${prefixCls.value}-block`]: props.block,
|
`${prefixCls.value}-element`,
|
||||||
}),
|
{
|
||||||
|
[`${prefixCls.value}-active`]: props.active,
|
||||||
|
[`${prefixCls.value}-block`]: props.block,
|
||||||
|
},
|
||||||
|
hashId.value,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
return () => {
|
return () => {
|
||||||
return (
|
return wrapSSR(
|
||||||
<div class={cls.value}>
|
<div class={cls.value}>
|
||||||
<Element {...props} prefixCls={`${prefixCls.value}-button`} />
|
<Element {...props} prefixCls={`${prefixCls.value}-button`} />
|
||||||
</div>
|
</div>,
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
|
@ -4,6 +4,7 @@ import useConfigInject from '../config-provider/hooks/useConfigInject';
|
||||||
import omit from '../_util/omit';
|
import omit from '../_util/omit';
|
||||||
import type { SkeletonElementProps } from './Element';
|
import type { SkeletonElementProps } from './Element';
|
||||||
import { skeletonElementProps } from './Element';
|
import { skeletonElementProps } from './Element';
|
||||||
|
import useStyle from './style';
|
||||||
|
|
||||||
export type SkeletonImageProps = Omit<SkeletonElementProps, 'size' | 'shape' | 'active'>;
|
export type SkeletonImageProps = Omit<SkeletonElementProps, 'size' | 'shape' | 'active'>;
|
||||||
|
|
||||||
|
@ -16,9 +17,12 @@ const SkeletonImage = defineComponent({
|
||||||
props: omit(skeletonElementProps(), ['size', 'shape', 'active']),
|
props: omit(skeletonElementProps(), ['size', 'shape', 'active']),
|
||||||
setup(props) {
|
setup(props) {
|
||||||
const { prefixCls } = useConfigInject('skeleton', props);
|
const { prefixCls } = useConfigInject('skeleton', props);
|
||||||
const cls = computed(() => classNames(prefixCls.value, `${prefixCls.value}-element`));
|
const [wrapSSR, hashId] = useStyle(prefixCls);
|
||||||
|
const cls = computed(() =>
|
||||||
|
classNames(prefixCls.value, `${prefixCls.value}-element`, hashId.value),
|
||||||
|
);
|
||||||
return () => {
|
return () => {
|
||||||
return (
|
return wrapSSR(
|
||||||
<div class={cls.value}>
|
<div class={cls.value}>
|
||||||
<div class={`${prefixCls.value}-image`}>
|
<div class={`${prefixCls.value}-image`}>
|
||||||
<svg
|
<svg
|
||||||
|
@ -29,7 +33,7 @@ const SkeletonImage = defineComponent({
|
||||||
<path d={path} class={`${prefixCls.value}-image-path`} />
|
<path d={path} class={`${prefixCls.value}-image-path`} />
|
||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>,
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
|
@ -5,6 +5,7 @@ import useConfigInject from '../config-provider/hooks/useConfigInject';
|
||||||
import type { SkeletonElementProps } from './Element';
|
import type { SkeletonElementProps } from './Element';
|
||||||
import Element, { skeletonElementProps } from './Element';
|
import Element, { skeletonElementProps } from './Element';
|
||||||
import omit from '../_util/omit';
|
import omit from '../_util/omit';
|
||||||
|
import useStyle from './style';
|
||||||
|
|
||||||
export interface SkeletonInputProps extends Omit<SkeletonElementProps, 'size' | 'shape'> {
|
export interface SkeletonInputProps extends Omit<SkeletonElementProps, 'size' | 'shape'> {
|
||||||
size?: 'large' | 'small' | 'default';
|
size?: 'large' | 'small' | 'default';
|
||||||
|
@ -21,17 +22,23 @@ const SkeletonInput = defineComponent({
|
||||||
},
|
},
|
||||||
setup(props) {
|
setup(props) {
|
||||||
const { prefixCls } = useConfigInject('skeleton', props);
|
const { prefixCls } = useConfigInject('skeleton', props);
|
||||||
|
const [wrapSSR, hashId] = useStyle(prefixCls);
|
||||||
const cls = computed(() =>
|
const cls = computed(() =>
|
||||||
classNames(prefixCls.value, `${prefixCls.value}-element`, {
|
classNames(
|
||||||
[`${prefixCls.value}-active`]: props.active,
|
prefixCls.value,
|
||||||
[`${prefixCls.value}-block`]: props.block,
|
`${prefixCls.value}-element`,
|
||||||
}),
|
{
|
||||||
|
[`${prefixCls.value}-active`]: props.active,
|
||||||
|
[`${prefixCls.value}-block`]: props.block,
|
||||||
|
},
|
||||||
|
hashId.value,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
return () => {
|
return () => {
|
||||||
return (
|
return wrapSSR(
|
||||||
<div class={cls.value}>
|
<div class={cls.value}>
|
||||||
<Element {...props} prefixCls={`${prefixCls.value}-input`} />
|
<Element {...props} prefixCls={`${prefixCls.value}-input`} />
|
||||||
</div>
|
</div>,
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
|
@ -9,6 +9,7 @@ import type { SkeletonParagraphProps } from './Paragraph';
|
||||||
import Paragraph from './Paragraph';
|
import Paragraph from './Paragraph';
|
||||||
import useConfigInject from '../config-provider/hooks/useConfigInject';
|
import useConfigInject from '../config-provider/hooks/useConfigInject';
|
||||||
import Element from './Element';
|
import Element from './Element';
|
||||||
|
import useStyle from './style';
|
||||||
|
|
||||||
/* This only for skeleton internal. */
|
/* This only for skeleton internal. */
|
||||||
type SkeletonAvatarProps = Omit<AvatarProps, 'active'>;
|
type SkeletonAvatarProps = Omit<AvatarProps, 'active'>;
|
||||||
|
@ -89,6 +90,8 @@ const Skeleton = defineComponent({
|
||||||
}),
|
}),
|
||||||
setup(props, { slots }) {
|
setup(props, { slots }) {
|
||||||
const { prefixCls, direction } = useConfigInject('skeleton', props);
|
const { prefixCls, direction } = useConfigInject('skeleton', props);
|
||||||
|
const [wrapSSR, hashId] = useStyle(prefixCls);
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
const { loading, avatar, title, paragraph, active, round } = props;
|
const { loading, avatar, title, paragraph, active, round } = props;
|
||||||
const pre = prefixCls.value;
|
const pre = prefixCls.value;
|
||||||
|
@ -152,13 +155,14 @@ const Skeleton = defineComponent({
|
||||||
[`${pre}-active`]: active,
|
[`${pre}-active`]: active,
|
||||||
[`${pre}-rtl`]: direction.value === 'rtl',
|
[`${pre}-rtl`]: direction.value === 'rtl',
|
||||||
[`${pre}-round`]: round,
|
[`${pre}-round`]: round,
|
||||||
|
[hashId.value]: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return wrapSSR(
|
||||||
<div class={cls}>
|
<div class={cls}>
|
||||||
{avatarNode}
|
{avatarNode}
|
||||||
{contentNode}
|
{contentNode}
|
||||||
</div>
|
</div>,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return slots.default?.();
|
return slots.default?.();
|
||||||
|
|
|
@ -17,7 +17,7 @@ Skeleton contains sub component.
|
||||||
</docs>
|
</docs>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="article">
|
<a-space direction="vertical" style="width: 100%" :size="16">
|
||||||
<a-skeleton :loading="loading">
|
<a-skeleton :loading="loading">
|
||||||
<div>
|
<div>
|
||||||
<h4>Ant Design Vue, a design language</h4>
|
<h4>Ant Design Vue, a design language</h4>
|
||||||
|
@ -29,7 +29,7 @@ Skeleton contains sub component.
|
||||||
</div>
|
</div>
|
||||||
</a-skeleton>
|
</a-skeleton>
|
||||||
<a-button :disabled="loading" @click="showSkeleton">Show Skeleton</a-button>
|
<a-button :disabled="loading" @click="showSkeleton">Show Skeleton</a-button>
|
||||||
</div>
|
</a-space>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent, ref } from 'vue';
|
import { defineComponent, ref } from 'vue';
|
||||||
|
@ -50,11 +50,3 @@ export default defineComponent({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
<style scoped>
|
|
||||||
.article h4 {
|
|
||||||
margin-bottom: 16px;
|
|
||||||
}
|
|
||||||
.article button {
|
|
||||||
margin-top: 16px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
|
@ -1,285 +0,0 @@
|
||||||
@import '../../style/themes/index';
|
|
||||||
@import '../../style/mixins/index';
|
|
||||||
|
|
||||||
@skeleton-prefix-cls: ~'@{ant-prefix}-skeleton';
|
|
||||||
@skeleton-avatar-prefix-cls: ~'@{skeleton-prefix-cls}-avatar';
|
|
||||||
@skeleton-title-prefix-cls: ~'@{skeleton-prefix-cls}-title';
|
|
||||||
@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-block-radius: 4px;
|
|
||||||
|
|
||||||
.@{skeleton-prefix-cls} {
|
|
||||||
display: table;
|
|
||||||
width: 100%;
|
|
||||||
|
|
||||||
&-header {
|
|
||||||
display: table-cell;
|
|
||||||
padding-right: @padding-md;
|
|
||||||
vertical-align: top;
|
|
||||||
|
|
||||||
// Avatar
|
|
||||||
.@{skeleton-avatar-prefix-cls} {
|
|
||||||
.skeleton-element-avatar();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&-content {
|
|
||||||
display: table-cell;
|
|
||||||
width: 100%;
|
|
||||||
vertical-align: top;
|
|
||||||
|
|
||||||
// Title
|
|
||||||
.@{skeleton-title-prefix-cls} {
|
|
||||||
width: 100%;
|
|
||||||
height: @skeleton-title-height;
|
|
||||||
margin-top: @margin-md;
|
|
||||||
background: @skeleton-color;
|
|
||||||
border-radius: @skeleton-block-radius;
|
|
||||||
|
|
||||||
+ .@{skeleton-paragraph-prefix-cls} {
|
|
||||||
margin-top: @skeleton-title-paragraph-margin-top;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// paragraph
|
|
||||||
.@{skeleton-paragraph-prefix-cls} {
|
|
||||||
padding: 0;
|
|
||||||
|
|
||||||
> li {
|
|
||||||
width: 100%;
|
|
||||||
height: @skeleton-paragraph-li-height;
|
|
||||||
list-style: none;
|
|
||||||
background: @skeleton-color;
|
|
||||||
border-radius: @skeleton-block-radius;
|
|
||||||
|
|
||||||
&:last-child:not(:first-child):not(:nth-child(2)) {
|
|
||||||
width: 61%;
|
|
||||||
}
|
|
||||||
|
|
||||||
+ li {
|
|
||||||
margin-top: @skeleton-paragraph-li-margin-top;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&-with-avatar &-content {
|
|
||||||
// Title
|
|
||||||
.@{skeleton-title-prefix-cls} {
|
|
||||||
margin-top: @margin-sm;
|
|
||||||
|
|
||||||
+ .@{skeleton-paragraph-prefix-cls} {
|
|
||||||
margin-top: @skeleton-paragraph-margin-top;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&-round &-content {
|
|
||||||
.@{skeleton-title-prefix-cls},
|
|
||||||
.@{skeleton-paragraph-prefix-cls} > li {
|
|
||||||
border-radius: 100px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// With active animation
|
|
||||||
&.@{skeleton-prefix-cls}-active {
|
|
||||||
& .@{skeleton-prefix-cls}-content {
|
|
||||||
.@{skeleton-title-prefix-cls},
|
|
||||||
.@{skeleton-paragraph-prefix-cls} > li {
|
|
||||||
.skeleton-color();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.@{skeleton-avatar-prefix-cls} {
|
|
||||||
.skeleton-color();
|
|
||||||
}
|
|
||||||
|
|
||||||
.@{skeleton-button-prefix-cls} {
|
|
||||||
.skeleton-color();
|
|
||||||
}
|
|
||||||
|
|
||||||
.@{skeleton-input-prefix-cls} {
|
|
||||||
.skeleton-color();
|
|
||||||
}
|
|
||||||
|
|
||||||
.@{skeleton-image-prefix-cls} {
|
|
||||||
.skeleton-color();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Skeleton Block Button, Input
|
|
||||||
&.@{skeleton-prefix-cls}-block {
|
|
||||||
width: 100%;
|
|
||||||
|
|
||||||
.@{skeleton-button-prefix-cls} {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.@{skeleton-input-prefix-cls} {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Skeleton element
|
|
||||||
&-element {
|
|
||||||
display: inline-block;
|
|
||||||
width: auto;
|
|
||||||
|
|
||||||
.@{skeleton-button-prefix-cls} {
|
|
||||||
.skeleton-element-button();
|
|
||||||
}
|
|
||||||
|
|
||||||
.@{skeleton-avatar-prefix-cls} {
|
|
||||||
.skeleton-element-avatar();
|
|
||||||
}
|
|
||||||
|
|
||||||
.@{skeleton-input-prefix-cls} {
|
|
||||||
.skeleton-element-input();
|
|
||||||
}
|
|
||||||
|
|
||||||
.@{skeleton-image-prefix-cls} {
|
|
||||||
.skeleton-element-image();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Button
|
|
||||||
.skeleton-element-button() {
|
|
||||||
display: inline-block;
|
|
||||||
vertical-align: top;
|
|
||||||
background: @skeleton-color;
|
|
||||||
border-radius: @border-radius-base;
|
|
||||||
|
|
||||||
.skeleton-element-button-size(@btn-height-base);
|
|
||||||
|
|
||||||
&-lg {
|
|
||||||
.skeleton-element-button-size(@btn-height-lg);
|
|
||||||
}
|
|
||||||
|
|
||||||
&-sm {
|
|
||||||
.skeleton-element-button-size(@btn-height-sm);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Avatar
|
|
||||||
.skeleton-element-avatar() {
|
|
||||||
display: inline-block;
|
|
||||||
vertical-align: top;
|
|
||||||
background: @skeleton-color;
|
|
||||||
|
|
||||||
.skeleton-element-avatar-size(@avatar-size-base);
|
|
||||||
|
|
||||||
&-lg {
|
|
||||||
.skeleton-element-avatar-size(@avatar-size-lg);
|
|
||||||
}
|
|
||||||
|
|
||||||
&-sm {
|
|
||||||
.skeleton-element-avatar-size(@avatar-size-sm);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Input
|
|
||||||
.skeleton-element-input() {
|
|
||||||
display: inline-block;
|
|
||||||
vertical-align: top;
|
|
||||||
background: @skeleton-color;
|
|
||||||
|
|
||||||
.skeleton-element-input-size(@input-height-base);
|
|
||||||
|
|
||||||
&-lg {
|
|
||||||
.skeleton-element-input-size(@input-height-lg);
|
|
||||||
}
|
|
||||||
|
|
||||||
&-sm {
|
|
||||||
.skeleton-element-input-size(@input-height-sm);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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);
|
|
||||||
|
|
||||||
&.@{skeleton-avatar-prefix-cls}-circle {
|
|
||||||
border-radius: 50%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.skeleton-element-button-size(@size) {
|
|
||||||
width: @size * 2;
|
|
||||||
min-width: @size * 2;
|
|
||||||
.skeleton-element-common-size(@size);
|
|
||||||
|
|
||||||
&.@{skeleton-button-prefix-cls}-circle {
|
|
||||||
width: @size;
|
|
||||||
min-width: @size;
|
|
||||||
border-radius: 50%;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.@{skeleton-button-prefix-cls}-round {
|
|
||||||
border-radius: @size;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.skeleton-element-input-size(@size) {
|
|
||||||
width: @size * 5;
|
|
||||||
min-width: @size * 5;
|
|
||||||
.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;
|
|
||||||
}
|
|
||||||
|
|
||||||
.skeleton-color() {
|
|
||||||
background: linear-gradient(
|
|
||||||
90deg,
|
|
||||||
@skeleton-color 25%,
|
|
||||||
@skeleton-to-color 37%,
|
|
||||||
@skeleton-color 63%
|
|
||||||
);
|
|
||||||
background-size: 400% 100%;
|
|
||||||
animation: ~'@{skeleton-prefix-cls}-loading' 1.4s ease infinite;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes ~"@{skeleton-prefix-cls}-loading" {
|
|
||||||
0% {
|
|
||||||
background-position: 100% 50%;
|
|
||||||
}
|
|
||||||
|
|
||||||
100% {
|
|
||||||
background-position: 0 50%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@import './rtl';
|
|
|
@ -0,0 +1,388 @@
|
||||||
|
import type { CSSObject } from '../../_util/cssinjs';
|
||||||
|
import { Keyframes } from '../../_util/cssinjs';
|
||||||
|
import type { FullToken, GenerateStyle } from '../../theme/internal';
|
||||||
|
import { genComponentStyleHook, mergeToken } from '../../theme/internal';
|
||||||
|
|
||||||
|
export type ComponentToken = {
|
||||||
|
color: string;
|
||||||
|
colorGradientEnd: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
const skeletonClsLoading = new Keyframes(`ant-skeleton-loading`, {
|
||||||
|
'0%': {
|
||||||
|
transform: 'translateX(-37.5%)',
|
||||||
|
},
|
||||||
|
'100%': {
|
||||||
|
transform: 'translateX(37.5%)',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
interface SkeletonToken extends FullToken<'Skeleton'> {
|
||||||
|
skeletonAvatarCls: string;
|
||||||
|
skeletonTitleCls: string;
|
||||||
|
skeletonParagraphCls: string;
|
||||||
|
skeletonButtonCls: string;
|
||||||
|
skeletonInputCls: string;
|
||||||
|
skeletonImageCls: string;
|
||||||
|
imageSizeBase: number;
|
||||||
|
skeletonTitleHeight: number;
|
||||||
|
skeletonBlockRadius: number;
|
||||||
|
skeletonParagraphLineHeight: number;
|
||||||
|
skeletonParagraphMarginTop: number;
|
||||||
|
skeletonLoadingBackground: string;
|
||||||
|
skeletonLoadingMotionDuration: string;
|
||||||
|
borderRadius: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
const genSkeletonElementCommonSize = (size: number): CSSObject => ({
|
||||||
|
height: size,
|
||||||
|
lineHeight: `${size}px`,
|
||||||
|
});
|
||||||
|
|
||||||
|
const genSkeletonElementAvatarSize = (size: number): CSSObject => ({
|
||||||
|
width: size,
|
||||||
|
...genSkeletonElementCommonSize(size),
|
||||||
|
});
|
||||||
|
|
||||||
|
const genSkeletonColor = (token: SkeletonToken): CSSObject => ({
|
||||||
|
position: 'relative',
|
||||||
|
// fix https://github.com/ant-design/ant-design/issues/36444
|
||||||
|
// https://monshin.github.io/202109/css/safari-border-radius-overflow-hidden/
|
||||||
|
/* stylelint-disable-next-line property-no-vendor-prefix,value-no-vendor-prefix */
|
||||||
|
zIndex: 0,
|
||||||
|
overflow: 'hidden',
|
||||||
|
background: 'transparent',
|
||||||
|
'&::after': {
|
||||||
|
position: 'absolute',
|
||||||
|
top: 0,
|
||||||
|
insetInlineEnd: '-150%',
|
||||||
|
bottom: 0,
|
||||||
|
insetInlineStart: '-150%',
|
||||||
|
background: token.skeletonLoadingBackground,
|
||||||
|
animationName: skeletonClsLoading,
|
||||||
|
animationDuration: token.skeletonLoadingMotionDuration,
|
||||||
|
animationTimingFunction: 'ease',
|
||||||
|
animationIterationCount: 'infinite',
|
||||||
|
content: '""',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const genSkeletonElementInputSize = (size: number): CSSObject => ({
|
||||||
|
width: size * 5,
|
||||||
|
minWidth: size * 5,
|
||||||
|
...genSkeletonElementCommonSize(size),
|
||||||
|
});
|
||||||
|
|
||||||
|
const genSkeletonElementAvatar = (token: SkeletonToken): CSSObject => {
|
||||||
|
const { skeletonAvatarCls, color, controlHeight, controlHeightLG, controlHeightSM } = token;
|
||||||
|
return {
|
||||||
|
[`${skeletonAvatarCls}`]: {
|
||||||
|
display: 'inline-block',
|
||||||
|
verticalAlign: 'top',
|
||||||
|
background: color,
|
||||||
|
...genSkeletonElementAvatarSize(controlHeight),
|
||||||
|
},
|
||||||
|
[`${skeletonAvatarCls}${skeletonAvatarCls}-circle`]: {
|
||||||
|
borderRadius: '50%',
|
||||||
|
},
|
||||||
|
[`${skeletonAvatarCls}${skeletonAvatarCls}-lg`]: {
|
||||||
|
...genSkeletonElementAvatarSize(controlHeightLG),
|
||||||
|
},
|
||||||
|
[`${skeletonAvatarCls}${skeletonAvatarCls}-sm`]: {
|
||||||
|
...genSkeletonElementAvatarSize(controlHeightSM),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const genSkeletonElementInput = (token: SkeletonToken): CSSObject => {
|
||||||
|
const {
|
||||||
|
controlHeight,
|
||||||
|
borderRadiusSM,
|
||||||
|
skeletonInputCls,
|
||||||
|
controlHeightLG,
|
||||||
|
controlHeightSM,
|
||||||
|
color,
|
||||||
|
} = token;
|
||||||
|
return {
|
||||||
|
[`${skeletonInputCls}`]: {
|
||||||
|
display: 'inline-block',
|
||||||
|
verticalAlign: 'top',
|
||||||
|
background: color,
|
||||||
|
borderRadius: borderRadiusSM,
|
||||||
|
...genSkeletonElementInputSize(controlHeight),
|
||||||
|
},
|
||||||
|
|
||||||
|
[`${skeletonInputCls}-lg`]: {
|
||||||
|
...genSkeletonElementInputSize(controlHeightLG),
|
||||||
|
},
|
||||||
|
|
||||||
|
[`${skeletonInputCls}-sm`]: {
|
||||||
|
...genSkeletonElementInputSize(controlHeightSM),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const genSkeletonElementImageSize = (size: number): CSSObject => ({
|
||||||
|
width: size,
|
||||||
|
...genSkeletonElementCommonSize(size),
|
||||||
|
});
|
||||||
|
|
||||||
|
const genSkeletonElementImage = (token: SkeletonToken): CSSObject => {
|
||||||
|
const { skeletonImageCls, imageSizeBase, color, borderRadiusSM } = token;
|
||||||
|
return {
|
||||||
|
[`${skeletonImageCls}`]: {
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center',
|
||||||
|
verticalAlign: 'top',
|
||||||
|
background: color,
|
||||||
|
borderRadius: borderRadiusSM,
|
||||||
|
...genSkeletonElementImageSize(imageSizeBase * 2),
|
||||||
|
[`${skeletonImageCls}-path`]: {
|
||||||
|
fill: '#bfbfbf',
|
||||||
|
},
|
||||||
|
[`${skeletonImageCls}-svg`]: {
|
||||||
|
...genSkeletonElementImageSize(imageSizeBase),
|
||||||
|
maxWidth: imageSizeBase * 4,
|
||||||
|
maxHeight: imageSizeBase * 4,
|
||||||
|
},
|
||||||
|
[`${skeletonImageCls}-svg${skeletonImageCls}-svg-circle`]: {
|
||||||
|
borderRadius: '50%',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
[`${skeletonImageCls}${skeletonImageCls}-circle`]: {
|
||||||
|
borderRadius: '50%',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
||||||
|
const genSkeletonElementButtonShape = (
|
||||||
|
token: SkeletonToken,
|
||||||
|
size: number,
|
||||||
|
buttonCls: string,
|
||||||
|
): CSSObject => {
|
||||||
|
const { skeletonButtonCls } = token;
|
||||||
|
return {
|
||||||
|
[`${buttonCls}${skeletonButtonCls}-circle`]: {
|
||||||
|
width: size,
|
||||||
|
minWidth: size,
|
||||||
|
borderRadius: '50%',
|
||||||
|
},
|
||||||
|
[`${buttonCls}${skeletonButtonCls}-round`]: {
|
||||||
|
borderRadius: size,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const genSkeletonElementButtonSize = (size: number): CSSObject => ({
|
||||||
|
width: size * 2,
|
||||||
|
minWidth: size * 2,
|
||||||
|
...genSkeletonElementCommonSize(size),
|
||||||
|
});
|
||||||
|
|
||||||
|
const genSkeletonElementButton = (token: SkeletonToken): CSSObject => {
|
||||||
|
const {
|
||||||
|
borderRadiusSM,
|
||||||
|
skeletonButtonCls,
|
||||||
|
controlHeight,
|
||||||
|
controlHeightLG,
|
||||||
|
controlHeightSM,
|
||||||
|
color,
|
||||||
|
} = token;
|
||||||
|
return {
|
||||||
|
[`${skeletonButtonCls}`]: {
|
||||||
|
display: 'inline-block',
|
||||||
|
verticalAlign: 'top',
|
||||||
|
background: color,
|
||||||
|
borderRadius: borderRadiusSM,
|
||||||
|
width: controlHeight * 2,
|
||||||
|
minWidth: controlHeight * 2,
|
||||||
|
...genSkeletonElementButtonSize(controlHeight),
|
||||||
|
},
|
||||||
|
...genSkeletonElementButtonShape(token, controlHeight, skeletonButtonCls),
|
||||||
|
|
||||||
|
[`${skeletonButtonCls}-lg`]: {
|
||||||
|
...genSkeletonElementButtonSize(controlHeightLG),
|
||||||
|
},
|
||||||
|
...genSkeletonElementButtonShape(token, controlHeightLG, `${skeletonButtonCls}-lg`),
|
||||||
|
|
||||||
|
[`${skeletonButtonCls}-sm`]: {
|
||||||
|
...genSkeletonElementButtonSize(controlHeightSM),
|
||||||
|
},
|
||||||
|
...genSkeletonElementButtonShape(token, controlHeightSM, `${skeletonButtonCls}-sm`),
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// =============================== Base ===============================
|
||||||
|
const genBaseStyle: GenerateStyle<SkeletonToken> = (token: SkeletonToken) => {
|
||||||
|
const {
|
||||||
|
componentCls,
|
||||||
|
skeletonAvatarCls,
|
||||||
|
skeletonTitleCls,
|
||||||
|
skeletonParagraphCls,
|
||||||
|
skeletonButtonCls,
|
||||||
|
skeletonInputCls,
|
||||||
|
skeletonImageCls,
|
||||||
|
controlHeight,
|
||||||
|
controlHeightLG,
|
||||||
|
controlHeightSM,
|
||||||
|
color,
|
||||||
|
padding,
|
||||||
|
marginSM,
|
||||||
|
borderRadius,
|
||||||
|
skeletonTitleHeight,
|
||||||
|
skeletonBlockRadius,
|
||||||
|
skeletonParagraphLineHeight,
|
||||||
|
controlHeightXS,
|
||||||
|
skeletonParagraphMarginTop,
|
||||||
|
} = token;
|
||||||
|
|
||||||
|
return {
|
||||||
|
[`${componentCls}`]: {
|
||||||
|
display: 'table',
|
||||||
|
width: '100%',
|
||||||
|
|
||||||
|
[`${componentCls}-header`]: {
|
||||||
|
display: 'table-cell',
|
||||||
|
paddingInlineEnd: padding,
|
||||||
|
verticalAlign: 'top',
|
||||||
|
|
||||||
|
// Avatar
|
||||||
|
[`${skeletonAvatarCls}`]: {
|
||||||
|
display: 'inline-block',
|
||||||
|
verticalAlign: 'top',
|
||||||
|
background: color,
|
||||||
|
...genSkeletonElementAvatarSize(controlHeight),
|
||||||
|
},
|
||||||
|
[`${skeletonAvatarCls}-circle`]: {
|
||||||
|
borderRadius: '50%',
|
||||||
|
},
|
||||||
|
[`${skeletonAvatarCls}-lg`]: {
|
||||||
|
...genSkeletonElementAvatarSize(controlHeightLG),
|
||||||
|
},
|
||||||
|
[`${skeletonAvatarCls}-sm`]: {
|
||||||
|
...genSkeletonElementAvatarSize(controlHeightSM),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
[`${componentCls}-content`]: {
|
||||||
|
display: 'table-cell',
|
||||||
|
width: '100%',
|
||||||
|
verticalAlign: 'top',
|
||||||
|
|
||||||
|
// Title
|
||||||
|
[`${skeletonTitleCls}`]: {
|
||||||
|
width: '100%',
|
||||||
|
height: skeletonTitleHeight,
|
||||||
|
background: color,
|
||||||
|
borderRadius: skeletonBlockRadius,
|
||||||
|
[`+ ${skeletonParagraphCls}`]: {
|
||||||
|
marginBlockStart: controlHeightSM,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
// paragraph
|
||||||
|
[`${skeletonParagraphCls}`]: {
|
||||||
|
padding: 0,
|
||||||
|
'> li': {
|
||||||
|
width: '100%',
|
||||||
|
height: skeletonParagraphLineHeight,
|
||||||
|
listStyle: 'none',
|
||||||
|
background: color,
|
||||||
|
borderRadius: skeletonBlockRadius,
|
||||||
|
'+ li': {
|
||||||
|
marginBlockStart: controlHeightXS,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
[`${skeletonParagraphCls}> li:last-child:not(:first-child):not(:nth-child(2))`]: {
|
||||||
|
width: '61%',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
[`&-round ${componentCls}-content`]: {
|
||||||
|
[`${skeletonTitleCls}, ${skeletonParagraphCls} > li`]: {
|
||||||
|
borderRadius,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
[`${componentCls}-with-avatar ${componentCls}-content`]: {
|
||||||
|
// Title
|
||||||
|
[`${skeletonTitleCls}`]: {
|
||||||
|
marginBlockStart: marginSM,
|
||||||
|
|
||||||
|
[`+ ${skeletonParagraphCls}`]: {
|
||||||
|
marginBlockStart: skeletonParagraphMarginTop,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// Skeleton element
|
||||||
|
[`${componentCls}${componentCls}-element`]: {
|
||||||
|
display: 'inline-block',
|
||||||
|
width: 'auto',
|
||||||
|
|
||||||
|
...genSkeletonElementButton(token),
|
||||||
|
...genSkeletonElementAvatar(token),
|
||||||
|
...genSkeletonElementInput(token),
|
||||||
|
...genSkeletonElementImage(token),
|
||||||
|
},
|
||||||
|
// Skeleton Block Button, Input
|
||||||
|
[`${componentCls}${componentCls}-block`]: {
|
||||||
|
width: '100%',
|
||||||
|
|
||||||
|
[`${skeletonButtonCls}`]: {
|
||||||
|
width: '100%',
|
||||||
|
},
|
||||||
|
|
||||||
|
[`${skeletonInputCls}`]: {
|
||||||
|
width: '100%',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// With active animation
|
||||||
|
[`${componentCls}${componentCls}-active`]: {
|
||||||
|
[`
|
||||||
|
${skeletonTitleCls},
|
||||||
|
${skeletonParagraphCls} > li,
|
||||||
|
${skeletonAvatarCls},
|
||||||
|
${skeletonButtonCls},
|
||||||
|
${skeletonInputCls},
|
||||||
|
${skeletonImageCls}
|
||||||
|
`]: {
|
||||||
|
...genSkeletonColor(token),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// ============================== Export ==============================
|
||||||
|
export default genComponentStyleHook(
|
||||||
|
'Skeleton',
|
||||||
|
token => {
|
||||||
|
const { componentCls } = token;
|
||||||
|
|
||||||
|
const skeletonToken = mergeToken<SkeletonToken>(token, {
|
||||||
|
skeletonAvatarCls: `${componentCls}-avatar`,
|
||||||
|
skeletonTitleCls: `${componentCls}-title`,
|
||||||
|
skeletonParagraphCls: `${componentCls}-paragraph`,
|
||||||
|
skeletonButtonCls: `${componentCls}-button`,
|
||||||
|
skeletonInputCls: `${componentCls}-input`,
|
||||||
|
skeletonImageCls: `${componentCls}-image`,
|
||||||
|
imageSizeBase: token.controlHeight * 1.5,
|
||||||
|
skeletonTitleHeight: token.controlHeight / 2,
|
||||||
|
skeletonBlockRadius: token.borderRadiusSM,
|
||||||
|
skeletonParagraphLineHeight: token.controlHeight / 2,
|
||||||
|
skeletonParagraphMarginTop: token.marginLG + token.marginXXS,
|
||||||
|
borderRadius: 100, // Large number to make capsule shape
|
||||||
|
skeletonLoadingBackground: `linear-gradient(90deg, ${token.color} 25%, ${token.colorGradientEnd} 37%, ${token.color} 63%)`,
|
||||||
|
skeletonLoadingMotionDuration: '1.4s',
|
||||||
|
});
|
||||||
|
return [genBaseStyle(skeletonToken)];
|
||||||
|
},
|
||||||
|
token => {
|
||||||
|
const { colorFillContent, colorFill } = token;
|
||||||
|
|
||||||
|
return {
|
||||||
|
color: colorFillContent,
|
||||||
|
colorGradientEnd: colorFill,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
);
|
|
@ -1,2 +0,0 @@
|
||||||
import '../../style/index.less';
|
|
||||||
import './index.less';
|
|
|
@ -1,48 +0,0 @@
|
||||||
@import '../../style/themes/index';
|
|
||||||
@import '../../style/mixins/index';
|
|
||||||
|
|
||||||
@skeleton-prefix-cls: ~'@{ant-prefix}-skeleton';
|
|
||||||
@skeleton-avatar-prefix-cls: ~'@{skeleton-prefix-cls}-avatar';
|
|
||||||
@skeleton-title-prefix-cls: ~'@{skeleton-prefix-cls}-title';
|
|
||||||
@skeleton-paragraph-prefix-cls: ~'@{skeleton-prefix-cls}-paragraph';
|
|
||||||
|
|
||||||
.@{skeleton-prefix-cls} {
|
|
||||||
&-rtl {
|
|
||||||
direction: rtl;
|
|
||||||
}
|
|
||||||
|
|
||||||
&-header {
|
|
||||||
.@{skeleton-prefix-cls}-rtl & {
|
|
||||||
padding-right: 0;
|
|
||||||
padding-left: 16px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// With active animation
|
|
||||||
&.@{skeleton-prefix-cls}-active {
|
|
||||||
& .@{skeleton-prefix-cls}-content {
|
|
||||||
.@{skeleton-title-prefix-cls},
|
|
||||||
.@{skeleton-paragraph-prefix-cls} > li {
|
|
||||||
.@{skeleton-prefix-cls}-rtl& {
|
|
||||||
animation-name: ~'@{skeleton-prefix-cls}-loading-rtl';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.@{skeleton-avatar-prefix-cls} {
|
|
||||||
.@{skeleton-prefix-cls}-rtl& {
|
|
||||||
animation-name: ~'@{skeleton-prefix-cls}-loading-rtl';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes ~"@{skeleton-prefix-cls}-loading-rtl" {
|
|
||||||
0% {
|
|
||||||
background-position: 0% 50%;
|
|
||||||
}
|
|
||||||
|
|
||||||
100% {
|
|
||||||
background-position: 100% 50%;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -49,7 +49,7 @@ import './layout/style';
|
||||||
import './list/style';
|
import './list/style';
|
||||||
import './tree-select/style';
|
import './tree-select/style';
|
||||||
import './drawer/style';
|
import './drawer/style';
|
||||||
import './skeleton/style';
|
// import './skeleton/style';
|
||||||
import './comment/style';
|
import './comment/style';
|
||||||
// import './config-provider/style';
|
// import './config-provider/style';
|
||||||
import './empty/style';
|
import './empty/style';
|
||||||
|
|
|
@ -32,7 +32,7 @@ import type { ComponentToken as NotificationComponentToken } from '../../notific
|
||||||
// import type { ComponentToken as ResultComponentToken } from '../../result/style';
|
// import type { ComponentToken as ResultComponentToken } from '../../result/style';
|
||||||
// import type { ComponentToken as SegmentedComponentToken } from '../../segmented/style';
|
// import type { ComponentToken as SegmentedComponentToken } from '../../segmented/style';
|
||||||
// import type { ComponentToken as SelectComponentToken } from '../../select/style';
|
// import type { ComponentToken as SelectComponentToken } from '../../select/style';
|
||||||
// import type { ComponentToken as SkeletonComponentToken } from '../../skeleton/style';
|
import type { ComponentToken as SkeletonComponentToken } from '../../skeleton/style';
|
||||||
// import type { ComponentToken as SliderComponentToken } from '../../slider/style';
|
// import type { ComponentToken as SliderComponentToken } from '../../slider/style';
|
||||||
// import type { ComponentToken as SpaceComponentToken } from '../../space/style';
|
// import type { ComponentToken as SpaceComponentToken } from '../../space/style';
|
||||||
import type { ComponentToken as SpinComponentToken } from '../../spin/style';
|
import type { ComponentToken as SpinComponentToken } from '../../spin/style';
|
||||||
|
@ -88,7 +88,7 @@ export interface ComponentTokenMap {
|
||||||
// Result?: ResultComponentToken;
|
// Result?: ResultComponentToken;
|
||||||
// Segmented?: SegmentedComponentToken;
|
// Segmented?: SegmentedComponentToken;
|
||||||
// Select?: SelectComponentToken;
|
// Select?: SelectComponentToken;
|
||||||
// Skeleton?: SkeletonComponentToken;
|
Skeleton?: SkeletonComponentToken;
|
||||||
// Slider?: SliderComponentToken;
|
// Slider?: SliderComponentToken;
|
||||||
Spin?: SpinComponentToken;
|
Spin?: SpinComponentToken;
|
||||||
Statistic?: {};
|
Statistic?: {};
|
||||||
|
|
Loading…
Reference in New Issue