GitHub

Usage

Set up the loading-ui registry, install components with the shadcn CLI, and wire them into real loading states.

loading-ui is distributed as a custom shadcn registry. The intended flow is:

  1. Make sure your app is already configured for the shadcn CLI.
  2. Add the @loading-ui registry to components.json.
  3. Install the components you want.
  4. Use them in pending, loading, or empty-state UI where motion adds clarity.

Prerequisites

Before installing from this registry, your project should already have:

  • a React app
  • Tailwind CSS configured
  • a components.json file for the shadcn CLI
  • path aliases that match your component setup

If you do not have components.json yet, initialize shadcn first:

pnpm dlx shadcn@latest init

Configure the Registry

Add @loading-ui to the registries section of your components.json:

components.json
{
  "$schema": "https://ui.shadcn.com/schema.json",
  "style": "base-nova",
  "tailwind": {
    "css": "app/global.css",
    "baseColor": "neutral",
    "cssVariables": true
  },
  "aliases": {
    "components": "@/components",
    "utils": "@/lib/utils",
    "ui": "@/components/ui",
    "lib": "@/lib",
    "hooks": "@/hooks"
  },
  "registries": {
    "@loading-ui": "https://loading-ui.com/r/{name}.json"
  }
}

Once that is in place, the CLI can resolve items like @loading-ui/ring.

Install a component

Use the shadcn CLI to pull a component into your project:

pnpm dlx shadcn add @loading-ui/ring

You can swap ring for any registry item you want to try:

  • @loading-ui/ring
  • @loading-ui/spokes
  • @loading-ui/classic
  • @loading-ui/analyzing-image

The installed files are yours. Edit names, classes, motion timing, and import paths to match your app.

Use in real UI

Keep loading indicators close to the action they describe. A good default is to pair motion with enough layout context that users can tell what is currently happening.

import { Ring } from "@/components/loading-ui/ring";
 
export function SaveButton({ isSaving }: { isSaving: boolean }) {
  return (
    <button
      type="button"
      disabled={isSaving}
      className="inline-flex items-center gap-2 rounded-md border px-3 py-2"
    >
      {isSaving ? <Ring className="size-4" /> : null}
      <span>{isSaving ? "Saving..." : "Save changes"}</span>
    </button>
  );
}

Usage guidelines

  • Prefer inline indicators when only part of the screen is pending.
  • Prefer skeletons or preserved layout when content shape matters more than motion.
  • Add accessible labels or nearby copy when the state is not obvious from context.
  • Avoid putting multiple competing loaders in the same viewport.

Copy-paste instead of CLI

If you do not want to use the registry flow, you can still copy component source directly from the docs and adapt it manually. That works well when your project structure differs from the default shadcn conventions or when you want tighter control over naming and placement.

Next Step

Browse Components when you want a specific primitive, or read Philosophy to understand the design constraints behind the library.