Shadcn Spinner Components

An indicator that can be used to show a loading state. All spinner styles work anywhere Radix UI or Base UI components are used. Browse our collection of 14 Shadcn Spinner variants.

Syncing

Processing your request
Please wait while we process your request. Do not refresh the page.

Validating...

Movement in the Day Care
Free Play: Painting and Crafting
Convert PDF
Create PDF single pages

Downloading (35%)

129 MB / 1000 MB

Processing payment...
$100.00
Unlock premium components
Get full control of shadcn/ui components, blocks and instances, including future additions.

Explore Shadcn Blocks

Ready-made page sections built with the same components.

View all blocks

Shadcn Spinner Component

The Shadcn Spinner is a small animated indicator that tells users something is happening in the background. Saving a form, sending a message, processing a payment or loading the next page all take a moment, and a spinner in the right place stops users from clicking twice or thinking the app has frozen.

Loading feedback shows up in many places, so this shadcn spinner collection puts it inside buttons, badges and inputs, over an avatar, in an empty state and in task, download and payment rows, along with custom sizes and colors. The spinner is a plain SVG icon built with shadcn/ui, React and Tailwind CSS with no primitive behind it, so it works anywhere Radix UI or Base UI components are used.

What is the Shadcn Spinner Component?

The shadcn/ui spinner is a Loader2Icon from Lucide with the Tailwind CSS animate-spin class, role="status" and aria-label="Loading". It is size-4 by default and inherits the current text color, so it matches the button, badge or text it sits next to without extra styling. Because it is just an SVG component, you can size it, recolor it or replace the icon with a single class or line of code.

Use a spinner for short waits where you cannot tell how long the task will take. When you know the progress, such as an upload percentage, a Progress bar is more helpful. When you are loading content with a known layout, like a list of cards, a Skeleton placeholder gives a better sense of what is coming and reduces layout shift.

Anatomy of the Shadcn Spinner

PartDescription
SpinnerThe only part. An SVG that accepts every SVG prop, including className for size and color and aria-label to describe what is loading.

14 Shadcn Spinner Variants

Each spinner variant listed here is previewed live at the top of this page, together with its source code and install command.

  • Basic and sizes: The default 16px spinner and a row of sizes from size-4 to size-10 set with a single class.
  • Custom color and icon: A spinner colored with a text class, and a version that swaps the default loader for a different Lucide icon.
  • In buttons and badges: A disabled Loading button, a destructive icon button and a Syncing badge, each with the spinner placed as an inline icon.
  • In inputs: A spinner inside an input group addon, and a message textarea that shows Validating next to the send button.
  • Empty state and avatar overlay: A processing screen with a title, description and Cancel button, and an avatar with a spinner on a dimmed overlay.
  • Task list: A checklist where finished steps show a check icon, the current step shows a spinner and upcoming steps are muted.
  • Download and payment items: Item rows with a spinner, a title such as Downloading (35%) or Processing payment, and a size, amount or cancel action.

How to Install the Shadcn Spinner Component

Set up shadcn/ui in your project if you have not already, then add the Shadcn UI Kit registry to your components.json once:

{
  "registries": {
    "@shadcnuikit": "https://shadcnuikit.com/r/{name}.json"
  }
}

Then install a spinner variant by its name:

npx shadcn@latest add @shadcnuikit/spinner1

The same command works with pnpm dlx, yarn dlx and bunx --bun. Each variant has a copy button for every package manager, and the code is added to your project as plain React and Tailwind CSS that you can edit freely.

How to Use the Shadcn Spinner Component

Import Spinner and render it wherever a task is running. Inside a button, disable the button and add data-icon="inline-start" so the padding adjusts to the icon.

"use client"

import { useState } from "react"

import { Button } from "@/components/ui/button"
import { Spinner } from "@/components/ui/spinner"

export function SaveButton() {
  const [saving, setSaving] = useState(false)

  async function handleSave() {
    setSaving(true)
    await fetch("/api/settings", { method: "POST" })
    setSaving(false)
  }

  return (
    <Button onClick={handleSave} disabled={saving}>
      {saving && <Spinner data-icon="inline-start" />}
      {saving ? "Saving..." : "Save changes"}
    </Button>
  )
}

Why Use the Shadcn Spinner Component

  • Tiny footprint: It is a single Lucide icon with a CSS animation, so it needs no extra package beyond lucide-react and adds almost nothing to your bundle.
  • Inherits its context: The spinner uses the current text color, so it matches buttons, badges and muted text automatically.
  • Accessible status: The status role and Loading label let screen readers know that content is being loaded.
  • Composable: It fits inside buttons, badges, input groups, avatars, empty states and list items without wrappers.
  • Easy to replace: Swap the icon or the animation in one file and every spinner in the project updates.

Common Spinner Use Cases

  • Submitting forms: Show progress inside the submit button while the request is sent.
  • Chat and AI input: Indicate that a message is being sent, validated or generated.
  • Background sync: Small spinners in badges or status bars while data is syncing.
  • Uploads and downloads: Rows that show a file is transferring next to its size and a cancel action.
  • Checkout: A clear processing state while a payment is being confirmed.
  • Multi step tasks: Mark the step that is currently running in an onboarding or import checklist.

Customizing the Shadcn Spinner

Change the size with size-* classes and the color with text-* classes, preferably theme tokens like text-muted-foreground or text-primary so the spinner follows your palette and dark mode. To use a different icon for the whole project, edit components/ui/spinner.tsx and replace Loader2Icon with any Lucide icon, keeping the role and label.

For example, a larger, muted spinner with a custom label:

<Spinner
  className="size-8 text-muted-foreground"
  aria-label="Loading comments"
/>

Spinner Accessibility

The spinner has role="status", which makes it a polite live region, and aria-label="Loading" as its accessible name. Override the label when the context is more specific, for example "Loading comments", so screen reader users know what they are waiting for.

The spinner is not focusable and has no keyboard interaction. When it replaces a button label, keep the button disabled and give it visible or sr-only text, and when the task finishes, move focus or announce the result so the change is not missed. Users who prefer reduced motion can be served a static icon with the motion-reduce:animate-none class.

Spinner Best Practices

  • Only show a spinner for waits that last longer than a moment; flashing it for a few milliseconds feels jumpy.
  • Place the spinner where the result will appear, such as inside the button that started the action.
  • Disable the control that started the task so the action cannot run twice.
  • Add a short text like Saving or Uploading next to the spinner when space allows.
  • Use a Progress bar instead when you know how far along the task is.
  • Prefer a Skeleton for loading page content with a known layout.

Components Related to Spinner

Shadcn Spinner FAQ

Render <Spinner data-icon="inline-start" /> before the label inside the Button and set disabled while the task is running. The data-icon attribute lets the button adjust its padding for the icon.

Pass Tailwind classes through className: size-6 or size-8 for the size, and a text color class such as text-muted-foreground or text-primary for the color. The spinner uses the current text color by default.

Yes. Open components/ui/spinner.tsx and replace Loader2Icon with another Lucide icon, such as LoaderIcon, keeping the animate-spin class, the status role and the aria-label.

Use a spinner for actions like saving or sending, where the result replaces a small area. Use a skeleton when loading page content, because it previews the layout and prevents content from jumping when data arrives.

Use InputGroup with InputGroupInput and put the Spinner in an InputGroupAddon with align="inline-end". For a textarea, use InputGroupTextarea and an addon with align="block-end" that holds the spinner, a status text such as Validating and the send button.

Looking for something else? Browse all shadcn/ui components or ready-made UI blocks built with them.