diff --git a/components/_util/theme/interface.ts b/components/_util/theme/interface.ts index cb31e53d7e..ce1a266794 100644 --- a/components/_util/theme/interface.ts +++ b/components/_util/theme/interface.ts @@ -28,6 +28,7 @@ import type { ComponentToken as RadioComponentToken } from '../../radio/style'; import type { ComponentToken as ResultComponentToken } from '../../result/style'; import type { ComponentToken as SegmentedComponentToken } from '../../segmented/style'; import type { ComponentToken as SelectComponentToken } from '../../select/style'; +import type { ComponentToken as SkeletonComponentToken } from '../../skeleton/style'; import type { ComponentToken as SliderComponentToken } from '../../slider/style'; import type { ComponentToken as SpaceComponentToken } from '../../space/style'; import type { ComponentToken as SpinComponentToken } from '../../spin/style'; @@ -101,7 +102,7 @@ export interface OverrideToken { Result?: ResultComponentToken; Segmented?: SegmentedComponentToken; Select?: SelectComponentToken; - Skeleton?: {}; + Skeleton?: SkeletonComponentToken; Slider?: SliderComponentToken; Spin?: SpinComponentToken; Statistic?: {}; diff --git a/components/skeleton/style/index.tsx b/components/skeleton/style/index.tsx index a42ebfaf39..f7bd65d800 100644 --- a/components/skeleton/style/index.tsx +++ b/components/skeleton/style/index.tsx @@ -2,9 +2,15 @@ import type { CSSObject } from '@ant-design/cssinjs'; import { Keyframes } from '@ant-design/cssinjs'; -import type { GenerateStyle, FullToken } from '../../_util/theme'; +import { TinyColor } from '@ctrl/tinycolor'; +import type { FullToken, GenerateStyle } from '../../_util/theme'; import { genComponentStyleHook, mergeToken } from '../../_util/theme'; +export type ComponentToken = { + color: string; + colorGradientEnd: string; +}; + const skeletonClsLoading = new Keyframes(`ant-skeleton-loading`, { '0%': { backgroundPosition: '100% 50%', @@ -21,14 +27,13 @@ interface SkeletonToken extends FullToken<'Skeleton'> { skeletonButtonCls: string; skeletonInputCls: string; skeletonImageCls: string; - skeletonColor: string; - skeletonToColor: string; imageSizeBase: number; - imageFontSizeBase: number; skeletonTitleHeight: number; skeletonBlockRadius: number; - skeletonParagraphLiHeight: number; + skeletonParagraphLineHeight: number; skeletonParagraphMarginTop: number; + skeletonLoadingBackground: string; + skeletonLoadingMotionDuration: string; borderRadius: number; } @@ -42,17 +47,14 @@ const genSkeletonElementAvatarSize = (size: number): CSSObject => ({ ...genSkeletonElementCommonSize(size), }); -const genSkeletonColor = (token: SkeletonToken): CSSObject => { - const { skeletonColor, skeletonToColor } = token; - return { - background: `linear-gradient(90deg, ${skeletonColor} 25%, ${skeletonToColor} 37%, ${skeletonColor} 63%)`, - backgroundSize: '400% 100%', - animationName: skeletonClsLoading, - animationDuration: '1.4s', // FIXME: magic - animationTimingFunction: 'ease', - animationIterationCount: 'infinite', - }; -}; +const genSkeletonColor = (token: SkeletonToken): CSSObject => ({ + background: token.skeletonLoadingBackground, + backgroundSize: '400% 100%', + animationName: skeletonClsLoading, + animationDuration: token.skeletonLoadingMotionDuration, + animationTimingFunction: 'ease', + animationIterationCount: 'infinite', +}); const genSkeletonElementInputSize = (size: number): CSSObject => ({ width: size * 5, @@ -61,13 +63,12 @@ const genSkeletonElementInputSize = (size: number): CSSObject => ({ }); const genSkeletonElementAvatar = (token: SkeletonToken): CSSObject => { - const { skeletonAvatarCls, skeletonColor, controlHeight, controlHeightLG, controlHeightSM } = - token; + const { skeletonAvatarCls, color, controlHeight, controlHeightLG, controlHeightSM } = token; return { [`${skeletonAvatarCls}`]: { display: 'inline-block', verticalAlign: 'top', - background: skeletonColor, + background: color, ...genSkeletonElementAvatarSize(controlHeight), }, [`${skeletonAvatarCls}${skeletonAvatarCls}-circle`]: { @@ -83,13 +84,12 @@ const genSkeletonElementAvatar = (token: SkeletonToken): CSSObject => { }; const genSkeletonElementInput = (token: SkeletonToken): CSSObject => { - const { controlHeight, skeletonInputCls, controlHeightLG, controlHeightSM, skeletonColor } = - token; + const { controlHeight, skeletonInputCls, controlHeightLG, controlHeightSM, color } = token; return { [`${skeletonInputCls}`]: { display: 'inline-block', verticalAlign: 'top', - background: skeletonColor, + background: color, ...genSkeletonElementInputSize(controlHeight), }, @@ -109,14 +109,14 @@ const genSkeletonElementImageSize = (size: number): CSSObject => ({ }); const genSkeletonElementImage = (token: SkeletonToken): CSSObject => { - const { skeletonImageCls, imageSizeBase, skeletonColor } = token; + const { skeletonImageCls, imageSizeBase, color } = token; return { [`${skeletonImageCls}`]: { display: 'flex', alignItems: 'center', justifyContent: 'center', verticalAlign: 'top', - background: skeletonColor, + background: color, ...genSkeletonElementImageSize(imageSizeBase * 2), [`${skeletonImageCls}-path`]: { fill: '#bfbfbf', @@ -160,19 +160,13 @@ const genSkeletonElementButtonSize = (size: number): CSSObject => ({ }); const genSkeletonElementButton = (token: SkeletonToken): CSSObject => { - const { - radiusBase, - skeletonButtonCls, - controlHeight, - controlHeightLG, - controlHeightSM, - skeletonColor, - } = token; + const { radiusBase, skeletonButtonCls, controlHeight, controlHeightLG, controlHeightSM, color } = + token; return { [`${skeletonButtonCls}`]: { display: 'inline-block', verticalAlign: 'top', - background: skeletonColor, + background: color, borderRadius: radiusBase, width: controlHeight * 2, minWidth: controlHeight * 2, @@ -205,13 +199,13 @@ const genBaseStyle: GenerateStyle = (token: SkeletonToken) => { controlHeight, controlHeightLG, controlHeightSM, - skeletonColor, + color, padding, marginSM, borderRadius, skeletonTitleHeight, skeletonBlockRadius, - skeletonParagraphLiHeight, + skeletonParagraphLineHeight, controlHeightXS, skeletonParagraphMarginTop, } = token; @@ -230,7 +224,7 @@ const genBaseStyle: GenerateStyle = (token: SkeletonToken) => { [`${skeletonAvatarCls}`]: { display: 'inline-block', verticalAlign: 'top', - background: skeletonColor, + background: color, ...genSkeletonElementAvatarSize(controlHeight), }, [`${skeletonAvatarCls}-circle`]: { @@ -252,7 +246,7 @@ const genBaseStyle: GenerateStyle = (token: SkeletonToken) => { [`${skeletonTitleCls}`]: { width: '100%', height: skeletonTitleHeight, - background: skeletonColor, + background: color, borderRadius: skeletonBlockRadius, [`+ ${skeletonParagraphCls}`]: { marginBlockStart: controlHeightSM, @@ -264,9 +258,9 @@ const genBaseStyle: GenerateStyle = (token: SkeletonToken) => { padding: 0, '> li': { width: '100%', - height: skeletonParagraphLiHeight, + height: skeletonParagraphLineHeight, listStyle: 'none', - background: skeletonColor, + background: color, borderRadius: skeletonBlockRadius, '+ li': { marginBlockStart: controlHeightXS, @@ -279,8 +273,8 @@ const genBaseStyle: GenerateStyle = (token: SkeletonToken) => { }, }, - [`${componentCls}-round ${componentCls}-content`]: { - [`${skeletonTitleCls}, ${skeletonTitleCls} > li`]: { + [`&-round ${componentCls}-content`]: { + [`${skeletonTitleCls}, ${skeletonParagraphCls} > li`]: { borderRadius, }, }, @@ -343,25 +337,31 @@ const genBaseStyle: GenerateStyle = (token: SkeletonToken) => { }; // ============================== Export ============================== -export default genComponentStyleHook('Skeleton', token => { - const { componentCls } = token; - - const skeletonToken = mergeToken(token, { - skeletonAvatarCls: `${componentCls}-avatar`, - skeletonTitleCls: `${componentCls}-title`, - skeletonParagraphCls: `${componentCls}-paragraph`, - skeletonButtonCls: `${componentCls}-button`, - skeletonInputCls: `${componentCls}-input`, - skeletonImageCls: `${componentCls}-image`, - skeletonColor: 'rgba(190,190,190,0.2)', // FIXME: hard code in v4 - skeletonToColor: 'rgba(129,129,129,.24)', // FIXME: hard code in v4 - imageSizeBase: 48, // FIXME: hard code in v4 - imageFontSizeBase: 24, // FIXME: hard code in v4 - skeletonTitleHeight: 16, // FIXME: hard code in v4 - skeletonBlockRadius: 4, // FIXME: hard code in v4 - skeletonParagraphLiHeight: 16, // FIXME: hard code in v4 - skeletonParagraphMarginTop: 28, // FIXME: hard code in v4 - borderRadius: 100, // FIXME: hard code in v4 - }); - return [genBaseStyle(skeletonToken)]; -}); +export default genComponentStyleHook( + 'Skeleton', + token => { + const { componentCls } = token; + + const skeletonToken = mergeToken(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.radiusLG, + 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)]; + }, + { + color: new TinyColor({ r: 190, g: 190, b: 190, a: 0.2 }).toRgbString(), + colorGradientEnd: new TinyColor({ r: 129, g: 129, b: 129, a: 0.24 }).toRgbString(), + }, +);