OpenSourceUIOpenSourceUIOpensource UI
GitHub—
  1. Home
  2. Components
  3. Loaders
  4. Spin Loader
Back to LoadersComponents / Loaders

Spin Loader

Free Loaders React component — SpinLoader. MIT licensed, copy-paste ready for Next.js and Tailwind CSS.

Minimal spinning loader built on a lucide icon — defaults to Loader, but pass any icon prop. Sizes: sm, md, lg.

Preview

Setup

How to use

Free for personal and commercial use. No UI attribution required. Include the MIT copyright notice when copying component source into your project. Read the MIT license.

  1. 1

    Run in your terminal:

    $npm install clsx tailwind-merge lucide-react
  2. 2

    Copy lib/cn.ts below. Skip if you already have cn().

  3. 3

    Copy the code below and create components/loaders/spin-loader.tsx in your project.

  4. 4

    Import and render:

    Example

    import { SpinLoader } from "@/components/loaders/spin-loader";

    <SpinLoader size="lg" iconClassName="text-sky-600" />

lib/cn.ts

1
2
3
4
5
6
import { type ClassValue, clsx } from "clsx";
import { twMerge } from "tailwind-merge";
 
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs));
}

components/loaders/spin-loader.tsx

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
import type { LucideIcon } from "lucide-react";
import { Loader } from "lucide-react";
 
import { cn } from "@/lib/cn";
 
export type SpinLoaderSize = "sm" | "md" | "lg";
 
export type SpinLoaderProps = Readonly<{
size?: SpinLoaderSize;
icon?: LucideIcon;
label?: string;
className?: string;
iconClassName?: string;
}>;
 
const SIZE: Record<SpinLoaderSize, number> = {
sm: 18,
md: 24,
lg: 32,
};
 
export function SpinLoader({
size = "md",
icon: Icon = Loader,
label = "Loading",
className,
iconClassName,
}: SpinLoaderProps) {
const iconSize = SIZE[size];
 
return (
<div
data-slot="spin-loader"
data-size={size}
className={cn("inline-flex items-center justify-center", className)}
role="status"
aria-live="polite"
aria-label={label}
>
<Icon
size={iconSize}
strokeWidth={2}
className={cn(
"animate-spin text-neutral-900 motion-reduce:animate-none",
iconClassName,
)}
aria-hidden
/>
</div>
);
}
PreviousNext

On this

page

Jump to a section on this page.

  • lib/cn.ts
  • components/loaders/spin-loader.tsx
Platinum slotAvailable

Feature your product here.

Sticky card next to every component — highest-intent placement.

Claim this card