thirukalyanamweb/src/components/common/Skeleton.jsx

109 lines
3.1 KiB
JavaScript

import React, { useEffect } from "react";
const STYLE_ID = "skeleton-shimmer-styles";
const injectSkeletonStyles = () => {
if (typeof document === "undefined") return;
if (document.getElementById(STYLE_ID)) return;
const style = document.createElement("style");
style.id = STYLE_ID;
style.textContent = `
.skeleton-shimmer {
position: relative;
overflow: hidden;
background: #e5e7eb;
}
.skeleton-shimmer::after {
content: "";
position: absolute;
inset: 0;
transform: translateX(-100%);
background: linear-gradient(90deg, rgba(255,255,255,0) 0%, rgba(255,255,255,0.7) 50%, rgba(255,255,255,0) 100%);
animation: skeleton-shimmer 1.6s infinite;
}
@keyframes skeleton-shimmer {
100% { transform: translateX(100%); }
}
`;
document.head.appendChild(style);
};
export const Skeleton = ({
width = "100%",
height = 12,
rounded = 6,
className = "",
}) => {
useEffect(() => {
injectSkeletonStyles();
}, []);
return (
<div
className={`skeleton-shimmer ${className}`}
style={{ width, height, borderRadius: rounded }}
/>
);
};
export const SkeletonText = ({
lines = 3,
gap = 10,
height = 12,
className = "",
}) => {
return (
<div className={className} style={{ display: "grid", gap }}>
{Array.from({ length: lines }).map((_, idx) => (
<Skeleton
key={idx}
height={height}
width={idx === lines - 1 ? "70%" : "100%"}
/>
))}
</div>
);
};
export const SkeletonPage = ({ className = "" }) => {
return (
<div className={className} style={{ width: "100%", padding: "20px" }}>
{/* Header */}
<div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: "24px" }}>
<Skeleton width="150px" height={40} />
<div style={{ display: "flex", gap: "16px" }}>
<Skeleton width="80px" height={36} />
<Skeleton width="80px" height={36} />
<Skeleton width="80px" height={36} />
</div>
</div>
{/* Banner */}
<div style={{ marginBottom: "32px" }}>
<Skeleton width="100%" height={250} rounded={12} />
</div>
{/* 4 Cards */}
<div style={{ display: "grid", gridTemplateColumns: "repeat(auto-fit, minmax(240px, 1fr))", gap: "24px", marginBottom: "40px" }}>
{Array.from({ length: 4 }).map((_, idx) => (
<div key={idx} style={{ display: "flex", flexDirection: "column", gap: "12px" }}>
<Skeleton width="100%" height={180} rounded={8} />
<Skeleton width="80%" height={20} />
<Skeleton width="60%" height={20} />
</div>
))}
</div>
{/* Footer */}
<div style={{ borderTop: "1px solid #e5e7eb", paddingTop: "32px", display: "grid", gridTemplateColumns: "repeat(auto-fit, minmax(200px, 1fr))", gap: "24px" }}>
<SkeletonText lines={3} />
<SkeletonText lines={3} />
<SkeletonText lines={3} />
<SkeletonText lines={3} />
</div>
</div>
);
};
export default Skeleton;