LoadingSkeleton
SM · 950B gzip budgetAnimated placeholder shapes for content loading states.
- Category
- Feedback & status
- Budget
- sm, single-purpose control
- External runtime
- React / React DOM only
axe fixtureSSR rendersource scanbundle budget
Preview
Live fixtureTry the component here. Locale-aware formatting and direction follow the selected language; example content and labels are not automatically translated. Overlay demos use interactive launchers.
Install
npx shadcn@latest add https://gear5-ui.vercel.app/r/loading-skeleton.jsonCopies the source into your project.
New here? Set up Tailwind and import aliases first →Source & props
Edit on GitHub ↗Prop types and inline documentation are included below. This is repository source; the installer rewrites shared imports for your project.
"use client";
import React from "react";
export interface LoadingSkeletonProps {
width?: string | number;
height?: string | number;
variant?: "text" | "circular" | "rectangular";
lines?: number;
style?: React.CSSProperties;
}
const shimmerKeyframes = `
@keyframes shimmer {
0% { background-position: -200% 0; }
100% { background-position: 200% 0; }
}
@media (prefers-reduced-motion: reduce) {
*, *::before, *::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
}
}
`;
export function LoadingSkeleton({
width = "100%",
height = "1rem",
variant = "text",
lines = 1,
style,
}: LoadingSkeletonProps) {
const baseStyle: React.CSSProperties = {
width,
height: variant === "circular" ? width : height,
borderRadius:
variant === "circular"
? "50%"
: variant === "rectangular"
? "0.5rem"
: "0.25rem",
background:
"linear-gradient(90deg, #e0e0e0 25%, #f0f0f0 50%, #e0e0e0 75%)",
backgroundSize: "200% 100%",
animation: "shimmer 1.5s infinite linear",
...style,
};
if (variant === "text" && lines > 1) {
return (
<>
<style>{shimmerKeyframes}</style>
<div style={{ display: "flex", flexDirection: "column", gap: "0.5rem" }}>
{Array.from({ length: lines }).map((_, i) => (
<div
key={i}
aria-hidden="true"
style={{
...baseStyle,
width: i === lines - 1 ? "60%" : "100%",
}}
/>
))}
</div>
</>
);
}
return (
<>
<style>{shimmerKeyframes}</style>
<div aria-hidden="true" style={baseStyle} />
</>
);
}
What CI checks
Quality contract- Bundled, minified and gzipped against its tier budget
- Audited by axe in the state previewed above
- Rendered through react-dom/server with no browser globals
- Scanned for network calls, dangerous sinks, and unguarded animation