GitHub

Ring

A circular indeterminate loader for inline actions, page transitions, and general pending states.

import { Ring } from "@/components/loading-ui/ring";

export function RingDemo() {

Installation

pnpm dlx shadcn@latest add @loading-ui/ring

Usage

import { Ring } from "@/components/loading-ui/ring";
<Ring />

Customization

Ring is intentionally simple to adapt. Most visual changes come from standard utility classes on the SVG itself, while animation behavior can be tuned to better match the pace and tone of the surrounding interface.

Size

Use the size-* utility class to change the size of the component.

import { Ring } from "@/components/loading-ui/ring";

export function RingSize() {

Color

Since the loader uses currentColor, you can change its appearance with any text color utility or inherited color from a parent container.

import { Ring } from "@/components/loading-ui/ring";

export function RingColor() {

Stroke Width

Because Ring is an SVG path, you can adjust the line thickness directly to make the spinner feel lighter or more assertive.

import { Ring } from "@/components/loading-ui/ring";

export function RingStrokeWidth() {

Duration

Set --duration when the spinner should feel calmer, more energetic, or better aligned with the rest of a transition.

import { Ring } from "@/components/loading-ui/ring";

export function RingDuration() {

Direction

You can also reverse the motion direction to better fit specific visual systems or pair the loader with other rotating elements in the UI.

import { Ring } from "@/components/loading-ui/ring";

export function RingDirection() {

Examples

These examples show how Ring behaves when it is embedded inside common interface patterns instead of standing alone. The loader works best when it inherits spacing, color, and alignment from surrounding primitives, so these compositions are usually the most useful reference when wiring it into product UI.

Button

Buttons are the most common place to use Ring for short-lived actions like submitting forms, saving settings, or kicking off async mutations.

import { Button } from "@/components/ui/button";
import { Ring } from "@/components/loading-ui/ring";

Badge

In badges, Ring works well for compact status labels like syncing, updating, or processing states that need to stay visible without taking over the layout.

SyncingUpdatingProcessing
import { Badge } from "@/components/ui/badge";
import { Ring } from "@/components/loading-ui/ring";

Input Group

Inside input groups, the loader can signal inline validation, request processing, or message sending without forcing the field into a separate loading view.

Validating...
import { ArrowUpIcon } from "lucide-react";

import {

Empty

For larger waiting states, Ring can sit inside an empty-state container to communicate that a full-screen or section-level operation is still in progress.

Processing your request

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

import { Button } from "@/components/ui/button";
import {
  Empty,