Skeleton
Skeleton.tsx
import React, { useState, useEffect } from 'react';
import styles from './Skeleton.module.css';
interface SkeletonProps {
type?: 'text' | 'rect';
rows?: number;
width?: string;
height?: string;
}
const Skeleton = ({ type = 'text', rows = 1, width, height }: SkeletonProps) => {
const [content, setContent] = useState<JSX.Element[]>([]);
useEffect(() => {
let elements: JSX.Element[] = [];
if (type === 'text') {
for (let i = 0; i < rows; i++) {
elements.push(<div key={i} className={styles.textSkeleton} style={{ width }} />);
}
} else if (type === 'rect') {
for (let i = 0; i < rows; i++) {
elements.push(<div key={i} className={styles.rectSkeleton} style={{ width, height }} />);
}
}
setContent(elements);
}, [type, rows, width, height]);
return <div className={styles.skeleton}>{content}</div>;
};
export default Skeleton;
Usage
import React from 'react';
import Skeleton from './Skeleton';
const App = () => {
return (
<div>
<Skeleton type="text" rows={3} width="200px" />
<Skeleton type="rect" rows={2} width="200px" height="50px" />
</div>
);
};
export default App;
Skeleton.module.css
.skeleton {
display: flex;
flex-direction: column;
margin-bottom: 1rem;
}
.skeleton-line {
height: 1rem;
width: 100%;
margin-bottom: 0.5rem;
border-radius: 0.25rem;
background-color: #ddd;
}
.skeleton-square {
height: 10rem;
width: 10rem;
margin-bottom: 1rem;
border-radius: 0.25rem;
background-color: #ddd;
}