Skip to content

Commit

Permalink
feat: ✨ implement skeleton
Browse files Browse the repository at this point in the history
  • Loading branch information
huang-xiao-jian committed Jun 9, 2020
1 parent 29e8d24 commit e2058cd
Show file tree
Hide file tree
Showing 4 changed files with 190 additions and 0 deletions.
49 changes: 49 additions & 0 deletions packages/Skeleton/Skeleton.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
.van-skeleton {
display: flex;
box-sizing: border-box;
width: 100%;
padding: 0 16px;
padding: var(--skeleton-padding, 0 16px);
}
.van-skeleton__avatar {
flex-shrink: 0;
margin-right: 16px;
margin-right: var(--padding-md, 16px);
background-color: #f2f3f5;
background-color: var(--skeleton-avatar-background-color, #f2f3f5);
}
.van-skeleton__avatar--round {
border-radius: 100%;
}
.van-skeleton__content {
flex: 1;
}
.van-skeleton__avatar + .van-skeleton__content {
padding-top: 8px;
padding-top: var(--padding-xs, 8px);
}
.van-skeleton__row,
.van-skeleton__title {
height: 16px;
height: var(--skeleton-row-height, 16px);
background-color: #f2f3f5;
background-color: var(--skeleton-row-background-color, #f2f3f5);
}
.van-skeleton__title {
margin: 0;
}
.van-skeleton__row:not(:first-child) {
margin-top: 12px;
margin-top: var(--skeleton-row-margin-top, 12px);
}
.van-skeleton__title + .van-skeleton__row {
margin-top: 20px;
}
.van-skeleton--animate {
animation: van-skeleton-blink 1.2s ease-in-out infinite;
}
@keyframes van-skeleton-blink {
50% {
opacity: 0.6;
}
}
115 changes: 115 additions & 0 deletions packages/Skeleton/Skeleton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
// packages
import React, { FunctionComponent, CSSProperties } from 'react';
import clsx from 'clsx';
import { View } from 'remax/wechat';
// internal
import { Switch, Case, Select } from '../tools/Switch';
import withDefaultProps from '../tools/with-default-props-advance';
import './Skeleton.css';

// 默认值填充属性
interface NeutralSkeletonProps {
row: number;
rowWidth: string | string[];
title: boolean;
titleWidth: string;
avatar: boolean;
avatarSize: string;
avatarShape: 'round' | 'square';
loading: boolean;
animate: boolean;
}

interface ExogenousSkeletonProps {
// 容器类名,用以覆盖内部
className?: string;
}

type SkeletonProps = NeutralSkeletonProps & ExogenousSkeletonProps;

const DefaultSkeletonProps: NeutralSkeletonProps = {
row: 0,
rowWidth: '100%',
title: false,
titleWidth: '40%',
avatar: false,
avatarSize: '32px',
avatarShape: 'round',
loading: true,
animate: true,
};

const Skeleton: FunctionComponent<SkeletonProps> = (props) => {
const {
className,
loading,
animate,
avatar,
avatarSize,
avatarShape,
title,
titleWidth,
row,
rowWidth,
children,
} = props;
const classnames = {
container: clsx(className, 'van-skeleton', {
'van-skeleton--animate': animate,
}),
avatar: clsx(
'van-skeleton__avatar',
`van-skeleton__avatar--${avatarShape}`
),
};
const stylesheets: Record<string, CSSProperties> = {
avatar: {
width: avatarSize,
height: avatarSize,
},
title: {
width: titleWidth,
},
};

// 占位符计算
const elements = Array.from({ length: row }).map((_, index) => ({
className: 'van-skeleton__row',
style: {
width: Array.isArray(rowWidth) ? rowWidth[index] : rowWidth,
},
}));

return (
<Switch>
<Case in={loading}>
<View className={classnames.container}>
<Select in={avatar}>
<View style={stylesheets.avatar} className={classnames.avatar} />
</Select>

<View className="van-skeleton__content">
<Select in={title}>
<View className="van-skeleton__title" style={stylesheets.title} />
</Select>
{elements.map((element, index) => (
// eslint-disable-next-line react/no-array-index-key
<View
key={index}
style={element.style}
className={element.className}
/>
))}
</View>
</View>
</Case>
<Case default>
<View className="van-skeleton__content">{children}</View>
</Case>
</Switch>
);
};

export default withDefaultProps<ExogenousSkeletonProps, NeutralSkeletonProps>(
DefaultSkeletonProps
)(Skeleton);
4 changes: 4 additions & 0 deletions packages/Skeleton/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
/**
* @description - nothing but export component
*/
export { default } from './Skeleton';
22 changes: 22 additions & 0 deletions public/pages/skeleton/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// packages
import * as React from 'react';
import { View, Text } from 'remax/wechat';

// internal
import Skeleton from '../../../packages/Skeleton';

export default () => {
return (
<View className="demo-block">
<Text className="demo-block__title">基础用法</Text>
<View className="demo-block__content">
<Skeleton title row={3} rowWidth={['100%', '100%', '80%']} />
</View>

<Text className="demo-block__title">显示头像</Text>
<View className="demo-block__content">
<Skeleton title avatar row={3} />
</View>
</View>
);
};

0 comments on commit e2058cd

Please sign in to comment.