Skip to main content

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;
}