Loader
A simple reusable loader in React
This is a minimal loading spinner: a one-line React component that shows or hides a div, plus the CSS that turns that div into a rotating ring. I keep something like this around because most projects need a quick "we're working on it" indicator long before they need a full loading-state library, and a single rotating element is enough to communicate progress without pulling in a dependency.
export default function Loader({ show }) {
return show ? <div className="loader"></div> : null;
}
/* Loader */
.loader {
border: 10px solid #eef0f1;
border-top: 10px solid #3b49df;
border-radius: 50%;
width: 50px;
height: 50px;
animation: spin 2s linear infinite;
}
@keyframes spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
How it works
The React side is deliberately dumb: Loader takes a show prop and returns the <div className="loader" /> when show is truthy, otherwise null. Returning null removes the element from the DOM entirely rather than just hiding it, so there's nothing animating in the background when it isn't needed.
The visual work is all CSS. The ring is a circle (border-radius: 50%) with a fixed width and height. The illusion of spinning comes from giving the whole border a light gray color (#eef0f1) and then overriding only border-top with a bright accent (#3b49df), so a single colored arc sits on an otherwise faint ring. The @keyframes spin rule rotates the element from 0deg to 360deg, and animation: spin 2s linear infinite runs that rotation continuously at a constant speed. linear matters here, an easing curve would make the spinner visibly speed up and slow down each loop, which looks wrong for a steady indicator.
When to use it
Reach for this for inline or full-screen "loading" states where you control the markup and just want a dependency-free spinner. Drive it from your own state, for example <Loader show={isLoading} />.
Tweak the 2s duration to taste: faster (around 0.8s) reads as "snappy," slower feels calmer. Resize by changing width/height together, and adjust the 10px border to keep the ring proportional. For accessibility, this is purely decorative markup, so consider adding role="status" and an aria-label (or visually hidden text like "Loading") on a wrapper so screen-reader users are told something is happening. If you support users who prefer reduced motion, you can wrap the animation in a @media (prefers-reduced-motion: reduce) query and swap to a static or fading indicator.