# Community (/docs/community)
Use the channel that matches the kind of feedback you have. Keeping discussions in the right place makes the project easier to maintain and easier to search later.
## Bugs and Regressions [#bugs-and-regressions]
Open a GitHub issue when something is broken, misleading, or inconsistent. Useful reports usually include:
* the component or page involved
* what you expected to happen
* what actually happened
* a minimal reproduction or screenshot when relevant
## Questions and Discussion [#questions-and-discussion]
If you are unsure whether something is a bug, or you want to talk through a pattern before opening an issue, use the project’s discussion channel if available. Community discussion is a better fit for open-ended API ideas, naming questions, and requests for guidance.
## Sharing Improvements [#sharing-improvements]
If you adapt a loading-ui component into a stronger pattern, that is useful project feedback. Examples, accessibility improvements, and docs fixes are all valid contributions, not just new components.
## Expectations [#expectations]
Keep discussion technical, respectful, and specific. Critique the implementation, not the person. The fastest way to get useful help is to be concrete about the problem you are solving.
## Want to contribute directly? [#want-to-contribute-directly]
Read [Contributing](/docs/contributing) for the expected workflow before opening a pull request.
# Contributing (/docs/contributing)
loading-ui is intentionally small, which makes contribution scope easier to reason about. Good contributions usually improve one of three things:
* the quality of an existing component
* the clarity of the docs
* the consistency of the registry and examples
## Before opening a pull request [#before-opening-a-pull-request]
* Check for an existing issue or open PR covering the same problem.
* For larger additions, align on direction first instead of building in isolation.
* Keep proposals narrow. Small, reviewable changes move faster here than broad rewrites.
## Local development [#local-development]
Install dependencies and run the site locally:
```bash
bun install
bun run dev
```
If you change registry items, rebuild the generated registry artifacts:
```bash
bun run build:registry
```
## What to update [#what-to-update]
Changes should stay coherent across the repo:
* component updates should include docs where public behavior changes
* docs examples should reflect real install and usage paths
* generated registry output should be rebuilt when source registry items change
## Component contributions [#component-contributions]
The bar for a new loading component is higher than "looks nice in isolation". It should also be:
* easy to understand at a glance
* reusable across real product states
* straightforward to customize after installation
* compatible with the existing registry structure
If a component is highly specific, it may belong in an app codebase or example gallery instead of the main registry.
## Documentation contributions [#documentation-contributions]
Docs live in `content/docs`. Prioritize clear setup steps, honest tradeoffs, and examples that match the actual repository structure. If the docs imply a workflow the repo does not support, fix the docs or the workflow so they agree.
## Pull request notes [#pull-request-notes]
When you open a PR, explain:
* what problem it solves
* why this approach fits the project
* whether docs or generated files were updated
That context matters more than a long edit summary.
# Introduction (/docs)
**loading-ui** is a small custom registry of loading indicators for modern React apps. It follows the same copy-paste and CLI-friendly model popularized by [shadcn/ui](https://ui.shadcn.com), but stays focused on one job: giving your product better pending states without introducing a heavy design system or animation framework.
The project currently ships a compact set of primitives that are meant to drop into the UI you already have instead of forcing a separate visual language.
## Why loading-ui exists [#why-loading-ui-exists]
Most teams either ship generic spinners everywhere or rebuild the same loading patterns per product surface. loading-ui sits in the middle:
* focused components instead of a full UI kit
* open code you can own after installation
* registry-based distribution that fits into existing shadcn-style workflows
* simple primitives that are easy to adapt to your spacing, color, and motion tokens
## How it fits into your stack [#how-it-fits-into-your-stack]
loading-ui is designed for apps already using React, Tailwind CSS, and a `components.json` setup compatible with the shadcn CLI. If that is already how your project works, the install path is short: add the registry, install a component, and style it like the rest of your UI.
## Open-source and community [#open-source-and-community]
loading-ui is open source, so the code you install is the code you can inspect, change, and ship. That matters for loading states because they usually need product-specific adjustments: timing, scale, accessibility text, or tighter integration with the rest of your interface.
The project is also meant to improve in public. If you find rough edges, want better docs, or have a loading pattern that feels broadly reusable, open an issue or contribute a fix. Small improvements are valuable here because the library is intentionally focused and every addition affects the overall quality bar.
## Start here [#start-here]
If you want to get a component into your app quickly, head to [Usage](/docs/usage). If you are evaluating whether the project matches your design values first, read [Philosophy](/docs/philosophy).
# Philosophy (/docs/philosophy)
loading-ui is opinionated about one thing: a loading state should help the user understand what is happening, not just prove that animation is possible.
## Motion should explain status [#motion-should-explain-status]
A loader is useful when it answers a question quickly:
* did my action start?
* is this section still fetching?
* should I wait, retry, or keep moving?
The animation itself is secondary. The job is communication.
## Loading states are part of the product [#loading-states-are-part-of-the-product]
Pending UI is not filler between real screens. It is part of the experience users actually see while saving, searching, uploading, and navigating. That means loading states should be designed with the same care as buttons, forms, and navigation.
## Small surface area, high adaptability [#small-surface-area-high-adaptability]
This project stays narrow on purpose. Instead of shipping a giant library of opinionated patterns, loading-ui focuses on a handful of primitives that are easy to install, inspect, and rewrite. The goal is to reduce repeated work without locking teams into a preset brand aesthetic.
## Restraint over novelty [#restraint-over-novelty]
A flashy animation can be useful in a landing page. In product UI, it often becomes noise. loading-ui favors components that:
* read clearly at small sizes
* look acceptable next to existing system UI
* can be slowed down, simplified, or restyled with minimal effort
* do not depend on decorative motion to make sense
## Open code over black boxes [#open-code-over-black-boxes]
Every installed component becomes part of your codebase. You can tune the animation curve, swap SVG paths, adjust accessibility text, or merge a loader into a bigger component. That ownership model is a core part of the project, not a side effect.
## Documentation should stay practical [#documentation-should-stay-practical]
The docs should help you evaluate and install components fast. That means straightforward setup steps, realistic examples, and language that reflects how teams actually ship UI.
## Related [#related]
* [Usage](/docs/usage) for setup and installation
* [Components](/docs/components) for individual component pages
* [Contributing](/docs/contributing) if you want to improve the registry
# Usage (/docs/usage)
loading-ui is distributed as a [custom shadcn registry](https://ui.shadcn.com/docs/registry). The intended flow is:
1. Make sure your app is already configured for the [shadcn CLI](https://ui.shadcn.com/docs/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 [#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:
```bash
npx shadcn@latest init
```
## Configure the Registry [#configure-the-registry]
Add `@loading-ui` to the `registries` section of your `components.json`:
```json title="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 [#install-a-component]
Use the shadcn CLI to pull a component into your project:
```bash
npx 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 [#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.
```tsx
import { Ring } from "@/components/loading-ui/ring";
export function SaveButton({ isSaving }: { isSaving: boolean }) {
return (
);
}
```
## Usage guidelines [#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 [#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 [#next-step]
Browse [Components](/docs/components) when you want a specific primitive, or read [Philosophy](/docs/philosophy) to understand the design constraints behind the library.
# Accordion Loader (/docs/components/accordion-loader)
`AccordionLoader` uses a monospace track, staggered block glyphs, and a
surface-aware mask color so the moving trail cuts cleanly through the track.
Credits to [shaah1d](https://x.com/shaah1d) for creating the initial animation.
## Installation [#installation]
Command
Manual
```bash
npx shadcn@latest add @loading-ui/accordion-loader
```
Copy and paste the following code into your project.
Update the import paths to match your project setup.
## Usage [#usage]
```tsx
import { AccordionLoader } from "@/components/loading-ui/accordion-loader";
```
```tsx
```
## Customization [#customization]
Use `trackLength` for the measured text track, `blocks` and `track` for the
unicode glyphs, and CSS variables such as `--duration`, `--delay`, and
`--mask-color` for motion and surface matching.
### Size [#size]
The loader is sized in `ch` units. Combine `trackLength` with text-size
utilities to change both geometry and scale.
### Color [#color]
Foreground color controls the track and the moving block trail.
### Duration [#duration]
Set `--duration` for faster or slower accordion motion.
### Glyphs [#glyphs]
Swap the unicode characters and set `--mask-color` when the loader sits on a
non-default surface.
# Analyzing image (/docs/components/analyzing-image)
`AnalyzingImage` is a scanning image placeholder for vision, OCR, upload review,
and image-understanding flows. It pairs especially well with shimmer text
components when the surrounding copy should feel like an active analysis state.
Credits to [dmytro](https://x.com/pqoqubbw/status/1913160002451153251) for re-creating the initial animation.
## Installation [#installation]
Command
Manual
```bash
npx shadcn@latest add @loading-ui/analyzing-image
```
Copy and paste the following code into your project.
Update the import paths to match your project setup.
## Usage [#usage]
```tsx
import { AnalyzingImage } from "@/components/loading-ui/analyzing-image";
```
```tsx
```
## Customization [#customization]
`AnalyzingImage` scales from `size-*` utilities and inherits `currentColor`. The
wipe mask defaults to `var(--background)`; on filled surfaces, set
`--loading-ui-analyzing-image-background` to the surface color so the scan feels
native to the container.
### Size [#size]
Use compact sizes for badges and buttons, and larger sizes for empty states or
image-analysis panels.
### Color [#color]
Color comes from `currentColor`, so text utilities or inherited foreground
colors are enough.
## Examples [#examples]
These examples use the component where an image is being read, described, or
processed. Pairing it with shimmer text keeps the visual and copy in the same
analysis language.
### Shimmer Text [#shimmer-text]
Use `TextShimmer` beside the icon when the label itself should feel active.
### Button [#button]
Buttons can use the icon for pending vision actions. Filled variants set the
mask background to match the button surface.
### Badge [#badge]
Badges work well for compact OCR, vision, and analysis labels.
### Empty [#empty]
Empty states can combine the icon with shimmer text while an uploaded image is
still being inspected.
# Arc (/docs/components/arc)
## Installation [#installation]
Command
Manual
```bash
npx shadcn@latest add @loading-ui/arc
```
Copy and paste the following code into your project.
Update the import paths to match your project setup.
## Usage [#usage]
```tsx
import { Arc } from "@/components/loading-ui/arc";
```
```tsx
```
## Customization [#customization]
`Arc` has a bit more visual weight than the lighter segmented spinners, so it works best when you want the loading state to feel deliberate and easy to spot. Since it is just a rotating bordered circle, the most useful adjustments come from size, color, border thickness, and timing.
### Size [#size]
Scale the loader up or down with `size-*` utilities depending on whether it sits inline or anchors a larger empty state.
### Color [#color]
`Arc` inherits `currentColor`, which makes it easy to align with brand accents, muted UI, or context-specific status colors.
### Border Width [#border-width]
Changing the border thickness noticeably shifts the feel of the component, especially at medium and larger sizes.
### Duration [#duration]
Set `--duration` when the loader should feel calm and backgrounded versus urgent and active.
## Examples [#examples]
These examples showcase the settings where `Arc` tends to read best: framed UI, more prominent surfaces, and states where the loader should feel a little more substantial than a minimal inline spinner.
### Button [#button]
Inside buttons, `Arc` works well when you want the action state to feel a bit more deliberate than a tiny inline indicator.
### Badge [#badge]
With a thinner border, `Arc` also fits nicely inside compact status pills for syncing and refresh states.
### Empty [#empty]
For section-level waiting states, the curved shape gives enough presence to anchor the empty state without needing extra ornament.
### Tabs [#tabs]
Use `Arc` inside tab content when a single panel is refreshing but the broader workspace remains interactive.
# Bars (/docs/components/bars)
## Installation [#installation]
Command
Manual
```bash
npx shadcn@latest add @loading-ui/bars
```
Copy and paste the following code into your project.
Update the import paths to match your project setup.
## Usage [#usage]
```tsx
import { Bars } from "@/components/loading-ui/bars";
```
```tsx
```
## Customization [#customization]
`Bars` is a compact activity indicator for dense UI. It stretches each bar to
the container height, divides width evenly across the `bars` count, and inherits
`currentColor`. Timing is controlled with `--duration` and `--delay`.
### Size [#size]
Set a stable height and width so the bars have room to breathe next to labels or
inside compact controls.
### Color [#color]
Use inherited foreground colors in product UI, or direct text utilities for
status-specific swatches.
### Duration [#duration]
Set `--duration` when the indicator should feel snappier or more patient.
### Stagger [#stagger]
Set `--delay` to control how tightly the bars follow each other.
### Bar Count [#bar-count]
Use `bars` to make the indicator denser for wider surfaces or simpler for tight
inline states.
## Examples [#examples]
These examples keep `Bars` close to operational UI: queues, indexing, and
processing states where a meter-like shape feels appropriate.
### Button [#button]
Buttons can use `Bars` when the action is actively processing but should still
feel compact.
### Badge [#badge]
Badges work well for small active, queued, or indexing labels.
### Input Group [#input-group]
Input groups keep indexing or search feedback next to the field it affects.
# Bobbing dots (/docs/components/bobbing-dots)
## Installation [#installation]
Command
Manual
```bash
npx shadcn@latest add @loading-ui/bobbing-dots
```
The registry entry pulls in **Motion** (`motion`); the CLI step should install it alongside the component.
Add Motion if you do not already use it (`motion` on npm; the import path is
`motion/react`).
Copy and paste the following code into your project.
Update the import paths to match your project setup.
## Usage [#usage]
```tsx
import { BobbingDots } from "@/components/loading-ui/bobbing-dots";
```
```tsx
```
## Customization [#customization]
`BobbingDots` mirrors `Dots` layout: percentage gap, `grow` dots, and `bg-current` (inherited foreground). Vertical motion is handled by Motion with a staggered delay per index. Use **`duration`** (seconds, default `1`) to speed up or slow the bounce without touching the keyframes.
### Size [#size]
Scale the row with width utilities; larger widths give each dot more room to travel visually.
### Color [#color]
Three vivid hex swatches, same idea as the blinking `Dots` showcase.
### Duration [#duration]
Pass `duration` as a number of seconds. Lower values feel snappier; higher values feel floatier.
### Dot count [#dot-count]
More dots add rhythm; keep widths generous so the bounce does not feel cramped.
## Examples [#examples]
Mix surfaces so the motion never feels copy-pasted: dashed alerts, sheets with breathing room, tabs with soft gradients, and popovers for micro-delights.
### Button [#button]
Spacing the label with `gap-2` keeps the bounce from colliding with button text.
### Badge [#badge]
Gradient-backed badges sell “play mode” energy without extra illustration.
### Sheet [#sheet]
Centered motion plus a sentence of context helps mobile-friendly workflows feel guided.
### Tabs [#tabs]
Let one tab hold the hero preview while the other stays lightweight; users can switch without losing the playful loop.
### Popover [#popover]
Keep copy short; the dots are the star of this transient surface.
# Bouncing dots (/docs/components/bouncing-dots)
## Installation [#installation]
Command
Manual
```bash
npx shadcn@latest add @loading-ui/bouncing-dots
```
Copy and paste the following code into your project.
Update the import paths to match your project setup.
## Usage [#usage]
```tsx
import { BouncingDots } from "@/components/loading-ui/bouncing-dots";
```
```tsx
```
## Customization [#customization]
`BouncingDots` shares the same flex row recipe as `Dots` and `Typing`: percentage gap, `grow` markers, and `bg-current` (inherited foreground). Each dot eases between smaller dimmer and larger brighter keyframes. Timing uses **`--duration`** (default **1.4s**); stagger delays stay fixed.
### Size [#size]
Control overall width; the dots share space evenly inside the row.
### Color [#color]
Arbitrary hex swatches for obvious documentation color.
### Duration [#duration]
Slow the bounce for calmer surfaces or speed it up for snappy microtasks.
### Dot count [#dot-count]
Add markers when the queue feels busier or you want a wider rhythm.
## Examples [#examples]
Surface variety keeps the bounce from feeling repetitive: alerts for status, a bottom sheet for mobile-friendly queues, tabs for live vs history, and a tight popover for async hints.
### Button [#button]
`gap-2` gives the row room to expand without crowding the label.
### Badge [#badge]
Compact chips for “spring load” or retry states.
### Alert [#alert]
Pair with operational copy when throughput is still stretching.
### Sheet [#sheet]
`side="bottom"` is ideal for thumb reach plus a centered bounce.
### Tabs [#tabs]
Let users compare live ingest against a quieter history tab.
### Popover [#popover]
Short copy, small footprint, one accent color on the dots.
# Classic (/docs/components/classic)
## Installation [#installation]
Command
Manual
```bash
npx shadcn@latest add @loading-ui/classic
```
Copy and paste the following code into your project.
Update the import paths to match your project setup.
## Usage [#usage]
```tsx
import { Classic } from "@/components/loading-ui/classic";
```
```tsx
```
## Customization [#customization]
`Classic` is the most familiar loading treatment in the set. It works especially well when you want a spinner that feels native to buttons, inputs, dialogs, and form-heavy UI without drawing too much attention to itself.
### Size [#size]
Adjust the overall footprint with `size-*` utilities depending on whether the spinner is sitting inline with text or acting as the main indicator in a small panel.
### Color [#color]
The spinner uses `currentColor`, so direct text color utilities or inherited color from a parent are enough to restyle it.
## Examples [#examples]
These examples focus on the patterns where `Classic` tends to feel most natural: compact controls, inline validation, and background activity states that should stay readable but unobtrusive.
### Button [#button]
Use `Classic` in action buttons when you want a familiar loading cue that blends into the control instead of dominating it.
### Input Group [#input-group]
In input groups, `Classic` works well for field-level checks and message drafting states that stay close to the control they affect.
# Clock ring (/docs/components/clock-ring)
## Installation [#installation]
Command
Manual
```bash
npx shadcn@latest add @loading-ui/clock-ring
```
Copy and paste the following code into your project.
Update the import paths to match your project setup.
## Usage [#usage]
```tsx
import { ClockRing } from "@/components/loading-ui/clock-ring";
```
```tsx
```
## Customization [#customization]
`ClockRing` keeps a full-strength guide ring with a single radial “hand,” so it naturally reads as **time, calendars, and scheduling** more than generic activity. Keep copy and placement aligned with that metaphor and it will feel intentional.
### Size [#size]
Match scale to the control or banner it sits beside so the hand stays visually balanced.
### Color [#color]
Pair semantic hues (for example warm tones for calendar sync) with theme-aware `dark:` variants when you need extra clarity.
### Ring weight [#ring-weight]
A heavier ring feels more like instrumentation; a lighter ring stays polite in forms and tables.
### Duration [#duration]
Slower rotations feel like background reconciliation; faster reads as a more immediate hold.
## Examples [#examples]
These examples emphasize **timelines and inputs**: alerts about sync lag, fields that resolve time zones, and lightweight popovers for maintenance context.
### Button [#button]
Use it when the action is explicitly waiting on a scheduler or clock-driven backend.
### Alert [#alert]
A dashed alert frame and warm accent color reinforce that the delay is temporal, not a hard failure.
### Input group [#input-group]
Localize feedback to the control when only one column is still resolving.
### Popover [#popover]
Popover content is ideal for short policy copy where the loader anchors a paragraph of explanation.
# Comet spinner (/docs/components/comet-spinner)
## Installation [#installation]
Command
Manual
```bash
npx shadcn@latest add @loading-ui/comet-spinner
```
Copy and paste the following code into your project.
Update the import paths to match your project setup.
## Usage [#usage]
```tsx
import { CometSpinner } from "@/components/loading-ui/comet-spinner";
```
```tsx
```
## Customization [#customization]
`CometSpinner` is built from layered `box-shadow` motion plus rotation, wrapped in a container query box so orbit math scales with `size-*`. Color comes from `currentColor`, and timing is driven by **`--duration`**.
### Size [#size]
The spinner is `aspect-square`; grow or shrink it with `size-*` depending on the density of the surrounding layout.
### Color [#color]
Set hue with text utilities; the head and tail inherit through the foreground color.
### Duration [#duration]
Set `--duration` with a CSS time value. The same value paces both the tail morph and the rotation.
### Geometry [#geometry]
`headScale` and `radiusScale` are clamped helpers that reshape the comet: smaller heads feel sharper, larger radii widen the sweep.
## Examples [#examples]
These examples lean into **burst, upload, and fast-lane** stories where the motion should feel directional.
### Button [#button]
Compact `size-*` on the icon slot keeps the comet legible beside label text.
### Badge [#badge]
In chips, a smaller comet still reads as motion without stealing focus from the label.
### Alert [#alert]
Pair the comet with a strong headline when the event is positive or neutral but still in flight.
### Tabs [#tabs]
Use tabs when only one surface is “burning hot” while the rest of the page stays cool and interactive.
# Concentric ring (/docs/components/concentric-ring)
## Installation [#installation]
Command
Manual
```bash
npx shadcn@latest add @loading-ui/concentric-ring
```
Copy and paste the following code into your project.
Update the import paths to match your project setup.
## Usage [#usage]
```tsx
import { ConcentricRing } from "@/components/loading-ui/concentric-ring";
```
```tsx
```
## Customization [#customization]
`ConcentricRing` has a tighter, more technical feel than a plain ring spinner. The overall look comes from the relationship between the outer guide ring and the inner rotating segment, so the most useful adjustments are the ones that change weight, color, pace, and overall scale.
### Size [#size]
Use `size-*` utilities to move the loader between compact inline states and more prominent framed layouts.
### Color [#color]
Both rings use `currentColor`, so the component can inherit tone from its parent or be styled directly with text color utilities.
### Ring Weight [#ring-weight]
Changing the border thickness shifts the component from delicate and precise to more assertive and mechanical.
### Duration [#duration]
Animation timing helps determine whether the loader feels calm and backgrounded or more active and urgent.
## Examples [#examples]
These examples focus on compact, structured UI where `ConcentricRing` feels particularly at home. It tends to work best in technical or dashboard-like contexts where the extra ring detail reads as intentional rather than decorative.
### Button [#button]
Inside buttons, `ConcentricRing` gives the pending state a slightly more engineered feel than a basic spinner.
### Badge [#badge]
In small status pills, the layered shape still reads clearly without becoming too heavy.
### Collapsible [#collapsible]
Within a collapsible task panel, it helps anchor a processing summary while deeper details remain visible below.
### Alert [#alert]
For visible but non-blocking activity, `ConcentricRing` makes a strong alert marker without overpowering the surrounding copy.
# Conveyor Loop (/docs/components/conveyor-loop)
`ConveyorLoop` moves a staggered block trail from left to right across a static
unicode track, then wraps back around without reversing direction.
Credits to [shaah1d](https://x.com/shaah1d) for creating the initial animation.
## Installation [#installation]
Command
Manual
```bash
npx shadcn@latest add @loading-ui/conveyor-loop
```
Copy and paste the following code into your project.
Update the import paths to match your project setup.
## Usage [#usage]
```tsx
import { ConveyorLoop } from "@/components/loading-ui/conveyor-loop";
```
```tsx
```
## Customization [#customization]
Use `trackLength`, `blocks`, and `track` to change the rail. The motion uses
`--duration` and `--delay`, while `--mask-color` controls how the moving glyphs
cut through the track.
### Size [#size]
Adjust `trackLength` with text-size utilities for different track widths.
### Color [#color]
The conveyor inherits text color.
### Duration [#duration]
Set `--duration` to make the conveyor faster or more deliberate.
### Glyphs [#glyphs]
Use alternate unicode characters and set `--mask-color` for tinted surfaces.
# Dash ring (/docs/components/dash-ring)
## Installation [#installation]
Command
Manual
```bash
npx shadcn@latest add @loading-ui/dash-ring
```
Copy and paste the following code into your project.
Update the import paths to match your project setup.
## Usage [#usage]
```tsx
import { DashRing } from "@/components/loading-ui/dash-ring";
```
```tsx
```
## Customization [#customization]
`DashRing` is an SVG with a faint track and an animated dash. The motion blends rotation with changing dash length, which reads well for **streaming**, **LLM output**, and other states where percent-complete is fuzzy.
### Size [#size]
Use `size-*` on the SVG root for inline controls, headers, and empty-state icons.
### Color [#color]
`stroke="currentColor"` on the circles means text and foreground utilities tint both the track and the active dash.
### Ring weight [#ring-weight]
Target the circles with a descendant selector to tune stroke width without forking the component.
### Animation cadence [#animation-cadence]
The dash morph and rotation timings are defined on the SVG’s `` elements. To change the feel, edit those `dur` values (and matching `keyTimes`) in `dash-ring.tsx`; they are not wired to Tailwind’s `animation-duration` utilities.
## Examples [#examples]
These examples lean into **fluid, in-flight** work: streaming copy, expandable diagnostics, and assistant surfaces.
### Button [#button]
In buttons, the dash ring signals blending or merging work rather than a simple fetch.
### Alert [#alert]
Use it when you want a calm, non-blocking heads-up that output quality is still converging.
### Collapsible [#collapsible]
Tuck verbose logs behind a collapsible while the spinner stays visible in the summary row.
### Input group [#input-group]
A textarea footer is a natural place to show synthesis status tied to the prompt above.
# Diamond (/docs/components/diamond)
`Diamond` uses eight square pixels arranged around a diamond path, each
fading in sequence. It reads especially well in game-inspired interfaces,
compact status surfaces, and loading states that want a little more character
than a standard ring.
## Installation [#installation]
Command
Manual
```bash
npx shadcn@latest add @loading-ui/diamond
```
Copy and paste the following code into your project.
Update the import paths to match your project setup.
## Usage [#usage]
```tsx
import { Diamond } from "@/components/loading-ui/diamond";
```
```tsx
```
## Customization [#customization]
`Diamond` keeps the original pixel choreography intact, so the main
controls are its overall `size-*` footprint and the foreground color it
inherits via `currentColor`.
### Size [#size]
Scale the SVG directly with `size-*` utilities.
### Color [#color]
Apply text color utilities when you want the pixel diamond to match the tone of
its parent surface or status state.
## Examples [#examples]
These examples focus on compact UI where the retro diamond shape can stay
legible without overpowering the rest of the interface.
### Button [#button]
Use the diamond as an inline action icon when the loading state should feel
playful but still precise.
### Badge [#badge]
Status chips are a natural fit because the compact square geometry stays crisp
at small sizes.
### Alert [#alert]
In alerts, the diamond loader gives longer-running system work a little more
personality while staying compact.
# Dots ring (/docs/components/dots-ring)
## Installation [#installation]
Command
Manual
```bash
npx shadcn@latest add @loading-ui/dots-ring
```
Copy and paste the following code into your project.
Update the import paths to match your project setup.
## Usage [#usage]
```tsx
import { DotsRing } from "@/components/loading-ui/dots-ring";
```
```tsx
```
## Customization [#customization]
`DotsRing` is more configurable than most of the simpler spinners in the set. Since the component exposes props for dot count, dot size, and ring radius, and uses `--duration` for pulse timing, it is a good fit when you want to tune the motion itself instead of only swapping utility classes around it.
### Size [#size]
Use `size-*` utilities to control the overall footprint of the ring in compact and larger layouts.
### Dot Count [#dot-count]
Increase or decrease the number of dots to make the motion feel denser or more minimal.
### Duration [#duration]
Set `--duration` to adjust how quickly the pulse travels around the ring.
### Dot Scale [#dot-scale]
Use `dotScale` to change the size of each dot relative to the overall ring.
### Radius Scale [#radius-scale]
The `radiusScale` prop controls how far the dots sit from the center, which changes how tight or airy the ring feels.
## Examples [#examples]
These examples focus on smaller, more interface-oriented contexts where `DotsRing` feels precise and a little more designed than a plain spinner, without becoming overly expressive.
### Badge [#badge]
In compact status pills, `DotsRing` gives you a more distinctive loading marker while still reading clearly at small sizes.
### Input Group [#input-group]
Inside input groups, it works well for inline checking and drafting states where the feedback should stay close to the field.
### Alert [#alert]
For visible but non-blocking system activity, `DotsRing` makes a good alert icon when you want something more refined than a single stroke spinner.
### Tabs [#tabs]
Within tabbed views, it can signal that one panel is still refreshing while the rest of the workspace remains available.
# Dots (/docs/components/dots)
## Installation [#installation]
Command
Manual
```bash
npx shadcn@latest add @loading-ui/dots
```
Copy and paste the following code into your project.
Update the import paths to match your project setup.
## Usage [#usage]
```tsx
import { Dots } from "@/components/loading-ui/dots";
```
```tsx
```
## Customization [#customization]
`Dots` lays out `aspect-square` markers with `grow` inside a flex row, so **width** on the root (for example `w-16`) is the main lever for overall scale. Each dot blinks on a staggered delay; color comes from `bg-current` and inherited foreground. The Color preview uses explicit hex swatches.
### Size [#size]
Widen or narrow the container and the dots distribute evenly with a percentage gap.
### Color [#color]
The first row uses semantic utilities; the second uses arbitrary hex so swatches stay obvious in any theme.
### Duration [#duration]
Set `--duration` to make the blink feel snappier or calmer.
### Dot count [#dot-count]
Pass `dots` when you want a longer ellipsis or a denser beat (three is the default).
## Examples [#examples]
These examples lean into **chat, drafts, and typing** metaphors. Pair with honest labels so users know it is progress, not decoration.
### Button [#button]
Disabled buttons plus dots communicate a short blocking action without swapping in a different icon set.
### Badge [#badge]
Tight chips for “typing” or “AI drafting” stay scannable because the row height matches the badge line box.
### Accordion [#accordion]
Use the accordion header as a live status surface while longer copy stays tucked in the panel.
### Input group [#input-group]
A textarea footer mirrors classic messenger UX: dots plus a single line of system copy.
### Empty [#empty]
Gradient framing makes the empty state feel transitional; swap to a message list once the first typist appears.
# Dual arc (/docs/components/dual-arc)
## Installation [#installation]
Command
Manual
```bash
npx shadcn@latest add @loading-ui/dual-arc
```
Copy and paste the following code into your project.
Update the import paths to match your project setup.
## Usage [#usage]
```tsx
import { DualArc } from "@/components/loading-ui/dual-arc";
```
```tsx
```
## Customization [#customization]
`DualArc` sits in a useful middle ground: more distinctive than a plain spinner, but still restrained enough for everyday product UI. Since the shape comes from borders and rotation, the most helpful changes are size, color, thickness, and pacing.
### Size [#size]
Scale the component with `size-*` utilities depending on whether it appears inline or anchors a slightly larger state.
### Color [#color]
Because the arcs use `currentColor`, they can easily inherit tone from the surrounding surface or be styled directly with text color utilities.
### Border Width [#border-width]
Border thickness changes how assertive the arcs feel, especially when you use the loader at medium or large sizes.
### Duration [#duration]
Set `--duration` to make the component read as either calm background activity or more active in-progress feedback.
## Examples [#examples]
These examples show where `DualArc` usually fits best: balanced interface patterns that need a clearer loading signal than the lightest spinners, but not the visual intensity of the more expressive variants.
### Badge [#badge]
In small status pills, `DualArc` stays readable while giving the label a bit more structure than a single stroke spinner.
### Input Group [#input-group]
Inside inputs and message composers, it helps communicate checking, drafting, or sending states without breaking the local flow.
### Alert [#alert]
For visible but non-blocking background work, `DualArc` gives alerts a stable activity marker that still feels refined.
### Tabs [#tabs]
Within tabbed workspaces, it can indicate a panel-level refresh while the broader interface stays interactive.
# Fade arc (/docs/components/fade-arc)
## Installation [#installation]
Command
Manual
```bash
npx shadcn@latest add @loading-ui/fade-arc
```
Copy and paste the following code into your project.
Update the import paths to match your project setup.
## Usage [#usage]
```tsx
import { FadeArc } from "@/components/loading-ui/fade-arc";
```
```tsx
```
## Customization [#customization]
`FadeArc` is an SVG made from two gradient-filled arc segments. The leading edge stays solid while the tail fades out, which gives you a softer motion read than a flat stroke spinner. Most tuning happens through size, color, timing, and spin direction.
### Size [#size]
Use `size-*` on the SVG root for inline controls, badges, and larger empty-state placements.
### Color [#color]
Both gradients use `currentColor`, so text and foreground utilities tint the arc and its fade in one step.
### Duration [#duration]
Set `--duration` when the loader should feel quick and responsive or slower and more backgrounded.
### Direction [#direction]
Reverse the spin when you want the motion to match nearby controls or other rotating elements.
## Examples [#examples]
These examples show where the softer gradient tail tends to fit best: sync work, panel refreshes, and assistant-style surfaces where the loader should feel present but not sharp.
### Button [#button]
In buttons, `FadeArc` reads clearly at small sizes without the harsh contrast of a single solid stroke.
### Badge [#badge]
Compact status pills benefit from the tapered tail because the motion stays visible even at `size-3.5`.
### Alert [#alert]
For non-blocking background jobs, the fade keeps the alert calm while still showing active progress.
### Input group [#input-group]
A textarea footer is a natural place to show generation or preview work tied to the prompt above.
### Tabs [#tabs]
Use it inside tab content when one panel is refreshing but the broader workspace stays interactive.
# Components (/docs/components)
# Infinity Square Snake (/docs/components/infinity-square-snake)
`InfinitySquareSnake` moves four staggered unicode glyphs through two joined
square loops. It keeps the path fixed and scales cleanly with font size.
Credits to [shaah1d](https://x.com/shaah1d) for creating the initial animation.
## Installation [#installation]
Command
Manual
```bash
npx shadcn@latest add @loading-ui/infinity-square-snake
```
Copy and paste the following code into your project.
Update the import paths to match your project setup.
## Usage [#usage]
```tsx
import { InfinitySquareSnake } from "@/components/loading-ui/infinity-square-snake";
```
```tsx
```
## Customization [#customization]
Use `blocks` for the four unicode trail glyphs. The path scales with text size,
and timing is controlled with `--duration` and `--delay`.
### Size [#size]
Scale the fixed infinity path with text-size utilities.
### Color [#color]
Apply text color utilities to the root.
### Duration [#duration]
Set `--duration` for the two-loop travel speed.
### Glyphs [#glyphs]
Provide four glyphs to customize the lead and trailing cells.
# Infinity Track (/docs/components/infinity-track)
`InfinityTrack` combines a static unicode infinity track with staggered moving
block masks. It is the tracked counterpart to `InfinitySquareSnake`.
Credits to [shaah1d](https://x.com/shaah1d) for creating the initial animation.
## Installation [#installation]
Command
Manual
```bash
npx shadcn@latest add @loading-ui/infinity-track
```
Copy and paste the following code into your project.
Update the import paths to match your project setup.
## Usage [#usage]
```tsx
import { InfinityTrack } from "@/components/loading-ui/infinity-track";
```
```tsx
```
## Customization [#customization]
Use `blocks` and `track` for unicode glyphs. The path scales with text size, and
`--duration`, `--delay`, and `--mask-color` control motion and surface matching.
### Size [#size]
Scale the tracked infinity path with text-size utilities.
### Color [#color]
The track and moving glyphs inherit text color.
### Duration [#duration]
Set `--duration` to tune the infinity loop.
### Glyphs [#glyphs]
Swap glyphs and set `--mask-color` when the loader sits on a tinted surface.
# Infinity (/docs/components/infinity)
`InfinityLoop` draws a continuous dash around an infinity path. It is a good
fit for live sync, monitoring, background jobs, and long-running states where
there is no useful percent-complete value.
## Installation [#installation]
Command
Manual
```bash
npx shadcn@latest add @loading-ui/infinity
```
Copy and paste the following code into your project.
Update the import paths to match your project setup.
## Usage [#usage]
```tsx
import { InfinityLoop } from "@/components/loading-ui/infinity";
```
```tsx
```
## Customization [#customization]
`InfinityLoop` is an SVG that inherits `currentColor`. Use stable height and
width utilities to keep the loop balanced, target the path for line weight, and
set `--duration` to tune the dash speed.
### Size [#size]
The loop reads best with a slightly wider box than it is tall.
### Color [#color]
The stroke uses `currentColor`, so text utilities and inherited foreground
colors are enough.
### Duration [#duration]
Set `--duration` when the loop should feel fast for active sync or slower for
ambient background work.
### Stroke Width [#stroke-width]
Target the path when the loop needs a lighter or heavier stroke at a given size.
## Examples [#examples]
These examples keep the loop tied to continuous states: syncing, monitoring,
streaming updates, and long-running background activity.
### Button [#button]
Buttons work well when a command starts an ongoing sync or keeps a connection
alive.
### Badge [#badge]
Badges can keep continuous status visible without adding a full loading row.
### Card [#card]
Cards give the loop enough room to explain a background process that continues
while the rest of the page stays interactive.
### Empty [#empty]
Empty states can use the loop for long-running setup, sync, or monitoring
states that may not finish immediately.
# Morphing infinity (/docs/components/morphing-infinity)
`MorphingInfinity` is an animated line icon that cycles through circle and
infinity forms. It is a good fit for AI replies, drafting flows, planning states,
and any interface where the wait state should feel deliberate instead of
generic.
## Installation [#installation]
Command
Manual
```bash
npx shadcn@latest add @loading-ui/morphing-infinity
```
Copy and paste the following code into your project.
Update the import paths to match your project setup.
## Usage [#usage]
```tsx
import { MorphingInfinity } from "@/components/loading-ui/morphing-infinity";
```
```tsx
```
## Customization [#customization]
`MorphingInfinity` is an SVG with a morphing path stroke. Use `className` and
`size-*` utilities to scale it inline, and inherit `currentColor` from the
surrounding text or foreground utilities.
### Compact [#compact]
Use a smaller `size-*` when the icon appears inside dense assistant panels,
toolbars, or inline status rows.
## Examples [#examples]
These examples place the morphing infinity in assistant-oriented surfaces where
a compact loading indicator needs to remain visible without becoming a full-page
loader.
### Alert [#alert]
Alerts can pair the icon with one concise line about the work in progress.
### Card [#card]
Cards keep the state attached to a specific assistant workspace or processing
panel.
### Tabs [#tabs]
Tabs work well when generated content and supporting material resolve at
different moments.
# Orbit ring (/docs/components/orbit-ring)
## Installation [#installation]
Command
Manual
```bash
npx shadcn@latest add @loading-ui/orbit-ring
```
Copy and paste the following code into your project.
Update the import paths to match your project setup.
## Usage [#usage]
```tsx
import { OrbitRing } from "@/components/loading-ui/orbit-ring";
```
```tsx
```
## Customization [#customization]
`OrbitRing` feels a bit more expansive than `ConcentricRing` because the moving arc sits outside the base ring. That makes it especially useful when you want a loader with a slightly wider footprint and a more dynamic silhouette.
### Size [#size]
Scale the component with `size-*` utilities depending on whether it appears inline or anchors a larger state.
### Color [#color]
The ring and orbiting segment inherit `currentColor`, so the component can easily match muted UI, primary accents, or stronger contextual tones.
### Ring Weight [#ring-weight]
Border thickness changes how crisp or substantial the orbit feels, especially at medium and larger sizes.
### Duration [#duration]
Animation speed changes the overall mood from calm background activity to something more energetic.
## Examples [#examples]
These examples lean into the wider, slightly more atmospheric quality of `OrbitRing`. It tends to read best in states that need a little more presence than a minimal inline spinner, but still want to stay clean and product-focused.
### Button [#button]
In buttons, `OrbitRing` works well when the action should feel active and noticeable without becoming flashy.
### Input Group [#input-group]
Inside input groups, it can signal resolving, drafting, or sending work while keeping the feedback local to the control.
### Empty [#empty]
For section-level waiting states, the outer orbit gives the loader enough presence to hold the layout on its own.
### Tabs [#tabs]
Within tabbed workspaces, it can indicate that one panel is still refreshing while the rest of the view remains available.
# Pulsating dots (/docs/components/pulsating-dots)
`PulsatingDots` uses soft scale and opacity changes to show ongoing work
without implying a direction. It is a good fit for queues, imports, background
processing, and compact UI surfaces where the state should feel alive but not
urgent.
## Installation [#installation]
Command
Manual
```bash
npx shadcn@latest add @loading-ui/pulsating-dots
```
Copy and paste the following code into your project.
Update the import paths to match your project setup.
## Usage [#usage]
```tsx
import { PulsatingDots } from "@/components/loading-ui/pulsating-dots";
```
```tsx
```
## Customization [#customization]
`PulsatingDots` is a flex row where each marker grows evenly inside the
available width. Color flows through `currentColor`, while `dots` and
`duration` let you tune the rhythm without changing the surrounding layout.
### Size [#size]
Control the row width; the dots divide that space evenly and keep their square
shape.
### Color [#color]
Use inherited foreground in product surfaces, or apply text color utilities when
the loader needs a stronger status tone.
### Duration [#duration]
`duration` is passed to Motion as seconds. Short cycles feel lively; longer
cycles feel calmer.
### Dot Count [#dot-count]
Three dots are the default, but wider queues can use four or five markers for a
denser pulse.
## Examples [#examples]
These examples use the loader for soft background work: staging files, warming
caches, queueing records, and small async hints.
### Button [#button]
The row is narrow enough for button labels while still showing the full pulse.
### Badge [#badge]
Badges work well for queue and retry states where the label still carries the
meaning.
### Input Group [#input-group]
Input groups keep the feedback local to the control that is still resolving.
### Sheet [#sheet]
Bottom sheets give the pulse enough breathing room for import or batch progress
without turning it into a full-page loading state.
### Popover [#popover]
Popovers are useful for tiny background tasks where a concise hint is enough.
# Pulse dot (/docs/components/pulse-dot)
[ChatGPT](https://chatgpt.com) uses this directly in the chat surface: one small dot that pulses at the end of the assistant turn until streamed text appears. `PulseDot` is the same pattern for your own products: copilots, support bots, and composer footers where a full spinner would feel heavy.
## Installation [#installation]
Command
Manual
```bash
npx shadcn@latest add @loading-ui/pulse-dot
```
Copy and paste the following code into your project.
Update the import paths to match your project setup.
## Usage [#usage]
```tsx
import { PulseDot } from "@/components/loading-ui/pulse-dot";
```
```tsx
```
## Customization [#customization]
The dot is a `rounded-full` block with `bg-current`, so **color** follows inherited foreground and `currentColor`. Scale sets how large the “breathing” motion feels relative to surrounding copy.
### Size [#size]
Chat UIs usually keep this tiny (`size-2` or `size-2.5` beside baseline text), larger in empty states or toolbars.
### Color [#color]
Because the dot is filled with `bg-current`, its hue follows the element’s **text color** / `currentColor`. The preview below uses `text-[#…]` on purpose so the swatches stay obvious; in real layouts you usually inherit from a parent or use whatever color API matches your theme.
### Duration [#duration]
Breathing speed uses `--duration`, defaulting to **1.2s** in the component.
## Examples [#examples]
### Button [#button]
Drop-in for “assistant is working” actions without changing button height.
### Badge [#badge]
Thread and model-status chips stay compact because the dot carries the motion alone.
### Input group [#input-group]
Mirrors the inline composer pattern: placeholder copy plus a dot at the trailing edge.
### Tabs [#tabs]
Use a tab panel to separate streaming copy from secondary material (sources, citations).
# Pulse (/docs/components/pulse)
## Installation [#installation]
Command
Manual
```bash
npx shadcn@latest add @loading-ui/pulse
```
Copy and paste the following code into your project.
Update the import paths to match your project setup.
## Usage [#usage]
```tsx
import { Pulse } from "@/components/loading-ui/pulse";
```
```tsx
```
## Customization [#customization]
`Pulse` animates a bordered ring with gentle scale and opacity breathing. It is deliberately **low urgency**: use it when you want presence without implying a hard error or precise percent complete.
### Size [#size]
Match the ring to icons, badges, and list rows with `size-*` utilities on the outer span.
### Color [#color]
The ring uses `border-current`, so the stroke follows inherited foreground and `currentColor`. The Color preview uses explicit hex swatches for clarity.
### Ring weight [#ring-weight]
Target the animated ring with a child selector if you need a lighter or heavier stroke.
### Duration [#duration]
Breathing speed follows `--duration`.
## Examples [#examples]
These examples emphasize **soft holds**: warm cache, idle polish, and tooltips that explain a temporary state.
### Button [#button]
Keeps pending actions feeling patient next to firmer spinners elsewhere in the app.
### Badge [#badge]
Works well for “standby” or “degraded but OK” badges where a full spinner would feel loud.
### Collapsible [#collapsible]
A dashed shell and muted copy reinforce that the section is optional context, not a blocker.
### Tooltip [#tooltip]
Short explanations plus a subtle pulse signal backoff or partial health without opening a dialog.
# Quarter ring (/docs/components/quarter-ring)
## Installation [#installation]
Command
Manual
```bash
npx shadcn@latest add @loading-ui/quarter-ring
```
Copy and paste the following code into your project.
Update the import paths to match your project setup.
## Usage [#usage]
```tsx
import { QuarterRing } from "@/components/loading-ui/quarter-ring";
```
```tsx
```
## Customization [#customization]
`QuarterRing` only paints the top-right quadrant of a ring, so it stays visually lighter than a full stroke while still reading clearly at small sizes. It fits inline labels, dense toolbars, and “quick pass” states.
### Size [#size]
Step through `size-*` utilities to match chips, table rows, and icon slots.
### Color [#color]
The arc uses `currentColor`, so inheritance and semantic text colors apply without extra props.
### Ring weight [#ring-weight]
Border thickness changes how punchy the arc feels against whitespace, especially next to monospace or tabular data.
### Duration [#duration]
Set `--duration` to slow the rotation for background tasks or speed it up for snappy micro-interactions.
## Examples [#examples]
These examples highlight **small-footprint** feedback: pills, empty states, and hover tips where a full ring would feel crowded.
### Button [#button]
The quarter arc keeps button height comfortable while the label carries most of the meaning.
### Badge [#badge]
Badges stay balanced because the spinner silhouette matches the height of adjacent text.
### Empty [#empty]
For “lightweight preview” empty states, the arc suggests work in progress without dominating the illustration slot.
### Tooltip [#tooltip]
Pair the loader with short explanatory copy when the delay is user-visible but not worth a modal.
# Ring (/docs/components/ring)
## Installation [#installation]
Command
Manual
```bash
npx shadcn@latest add @loading-ui/ring
```
Copy and paste the following code into your project.
Update the import paths to match your project setup.
## Usage [#usage]
```tsx
import { Ring } from "@/components/loading-ui/ring";
```
```tsx
```
## Customization [#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 [#size]
Use the `size-*` utility class to change the size of the component.
### Color [#color]
Since the loader uses `currentColor`, you can change its appearance with any text color utility or inherited color from a parent container.
### Stroke Width [#stroke-width]
Because `Ring` is an SVG path, you can adjust the line thickness directly to make the spinner feel lighter or more assertive.
### Duration [#duration]
Set `--duration` when the spinner should feel calmer, more energetic, or better aligned with the rest of a transition.
### Direction [#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.
## Examples [#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 [#button]
Buttons are the most common place to use `Ring` for short-lived actions like submitting forms, saving settings, or kicking off async mutations.
### Badge [#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.
### Input Group [#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.
### Empty [#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.
# Ripple (/docs/components/ripple)
## Installation [#installation]
Command
Manual
```bash
npx shadcn@latest add @loading-ui/ripple
```
Copy and paste the following code into your project.
Update the import paths to match your project setup.
## Usage [#usage]
```tsx
import { Ripple } from "@/components/loading-ui/ripple";
```
```tsx
```
## Customization [#customization]
`Ripple` is an SVG with two staggered circles: each ring grows and fades using SMIL animation. Color follows `currentColor` on the strokes, and the overall scale comes from `size-*` on the root.
### Size [#size]
Ripples read best with a little breathing room. Step from compact inline sizes up to hero-style empty states.
### Color [#color]
Tint with text utilities so the waves match primary actions, muted chrome, or brand accents.
### Ring weight [#ring-weight]
The group defaults to a medium stroke; narrow or embolden both rings together with a descendant selector on the ``.
### Animation cadence [#animation-cadence]
Expansion and fade timings are defined on the SVG `` elements (`dur`, `keySplines`, and the negative `begin` offset on the second ring). To change the rhythm, edit those values in `ripple.tsx`; they are not driven by Tailwind `animation-duration` utilities.
## Examples [#examples]
### Button [#button]
Keeps toolbar and form actions feeling “alive” while a background sweep runs.
### Badge [#badge]
Works in compact status chips where a full spinner would feel heavy.
### Alert [#alert]
Pair with honest copy when you want to signal active scanning rather than a hard error.
### Empty [#empty]
Ripples naturally occupy the focal point of an empty illustration slot.
# Satellite ring (/docs/components/satellite-ring)
## Installation [#installation]
Command
Manual
```bash
npx shadcn@latest add @loading-ui/satellite-ring
```
Copy and paste the following code into your project.
Update the import paths to match your project setup.
## Usage [#usage]
```tsx
import { SatelliteRing } from "@/components/loading-ui/satellite-ring";
```
```tsx
```
## Customization [#customization]
`SatelliteRing` reads like a small body in orbit: a muted guide ring and a solid dot that travels the perimeter. It shines when the story is fan-out, replication, or “almost there” propagation rather than a generic busy spinner.
### Size [#size]
Use `size-*` to balance the loader against labels, chips, and surrounding padding.
### Color [#color]
The guide ring and satellite both follow `currentColor`, so you can inherit from parents or set hue with text utilities.
### Ring weight [#ring-weight]
Thicker borders make the orbit feel more mechanical; thinner borders stay lighter in dense UIs.
### Duration [#duration]
Tune `--duration` to match calm background work versus a more urgent cadence.
## Examples [#examples]
These examples lean into **spread and status** narratives: rollouts, mesh relays, and badges that should feel like live systems rather than static chrome.
### Button [#button]
In buttons, the satellite gives a clear “work is moving through the fleet” cue without extra illustration.
### Badge [#badge]
Compact pills stay legible because the motion stays tight to the ring.
### Accordion [#accordion]
Inside an accordion, the loader can headline a section that is still converging while the rest of the checklist stays scannable.
### Sheet [#sheet]
A sheet is a good fit when the detail pane should explain *why* propagation is still running.
# Skeleton (/docs/components/skeleton)
`Skeleton` is a low-detail placeholder for content that has not loaded yet.
Shape each block to match the layout it will replace so the page stays stable
while data, images, or user details are still resolving.
## Installation [#installation]
Command
Manual
```bash
npx shadcn@latest add @loading-ui/skeleton
```
Copy and paste the following code into your project.
Update the import paths to match your project setup.
## Usage [#usage]
```tsx
import { Skeleton } from "@/components/loading-ui/skeleton";
```
```tsx
```
## Customization [#customization]
Use width, height, radius, and layout utilities to mirror the content that will
replace each skeleton. The pulse speed is controlled with `--duration`.
### Duration [#duration]
Set `--duration` on each skeleton, or on a parent wrapper, when a surface needs
a faster or calmer pulse.
## Examples [#examples]
These examples follow common loading layouts where skeletons work best: user
rows, content cards, paragraph copy, forms, and tabular data.
### Avatar [#avatar]
Use a circular skeleton beside text lines for user, account, or comment rows.
### Card [#card]
Cards can reserve media, title, metadata, and author space while the full
content is fetched.
### Text [#text]
Stack line skeletons with varied widths to suggest headings and body copy.
### Form [#form]
Form skeletons should preserve label, input, and action spacing so the final
fields do not shift into place.
### Table [#table]
Use repeated rows to hold dense layouts steady while records load.
# Spiral (/docs/components/spiral)
## Installation [#installation]
Command
Manual
```bash
npx shadcn@latest add @loading-ui/spiral
```
Copy and paste the following code into your project.
Update the import paths to match your project setup.
## Usage [#usage]
```tsx
import { Spiral } from "@/components/loading-ui/spiral";
```
```tsx
```
## Customization [#customization]
`Spiral` is a more characterful loader that builds its motion from dots moving around a circular path. The most meaningful changes come from dot density, how wide the spiral sits, and the overall size and color treatment.
### Size [#size]
Scale the component with `size-*` utilities depending on whether it appears inline or anchors a larger loading state.
### Color [#color]
Because each dot uses `currentColor`, the component can inherit the surrounding tone or be styled directly with any text color utility.
### Dot Count [#dot-count]
The `dots` prop changes the density of the motion path, from more minimal to more continuous.
### Radius [#radius]
Use the `radius` prop to tighten or widen the spiral without changing the outer size of the component.
## Examples [#examples]
These examples use `Spiral` in places where its motion can add a bit more personality to the waiting state instead of disappearing into the background.
### Button [#button]
In primary actions, `Spiral` gives the pending state a little more energy than a plain inline spinner.
### Collapsible [#collapsible]
Inside a collapsible processing panel, it helps anchor the summary while deeper details remain available underneath.
### Empty [#empty]
For featured waiting states, `Spiral` has enough presence to hold the layout without needing extra decoration.
### Tabs [#tabs]
In tabbed workspaces, it works well when one panel is still loading but the rest of the UI should stay usable.
# Spokes (/docs/components/spokes)
## Installation [#installation]
Command
Manual
```bash
npx shadcn@latest add @loading-ui/spokes
```
Copy and paste the following code into your project.
Update the import paths to match your project setup.
## Usage [#usage]
```tsx
import { Spokes } from "@/components/loading-ui/spokes";
```
```tsx
```
## Customization [#customization]
`Spokes` is a good fit when you want a loader that still reads clearly at small sizes without the visual weight of a continuous ring. It inherits `currentColor`, accepts standard SVG props, and can be tuned entirely with utility classes.
### Size [#size]
Scale the loader with `size-*` utilities depending on whether it sits inline with text, inside a control, or in a more prominent waiting state.
### Color [#color]
Because the stroke uses `currentColor`, the component can inherit surrounding text color or be styled directly with any text utility.
### Line Weight [#line-weight]
When you scale `Spokes` up, adjusting the stroke width helps keep the spinner balanced instead of feeling too thin or too heavy.
### Duration [#duration]
Set `--duration` to slow down calmer background work or tighten up quick action feedback.
## Examples [#examples]
These examples focus on the kinds of compact product UI where `Spokes` tends to work best. The segmented shape keeps the indicator noticeable without overpowering nearby text, borders, or status colors.
### Button [#button]
Use `Spokes` in buttons when the action is pending but the control should still feel lightweight and responsive.
### Badge [#badge]
For small status pills, `Spokes` is easier to tuck into a badge than a heavier spinner style.
### Input Group [#input-group]
Inside input groups, the loader can communicate inline validation, lookup, or send states without introducing a separate loading row.
### Alert [#alert]
For background tasks that should stay visible but not interrupt the flow, `Spokes` works well as a subtle activity marker inside an alert.
# Square Accordion (/docs/components/square-accordion)
`SquareAccordion` follows the same square edge as `SquareGrid`, but its timeline
holds at each corner to create an accordion-like trail collapse.
Credits to [shaah1d](https://x.com/shaah1d) for creating the initial animation.
## Installation [#installation]
Command
Manual
```bash
npx shadcn@latest add @loading-ui/square-accordion
```
Copy and paste the following code into your project.
Update the import paths to match your project setup.
## Usage [#usage]
```tsx
import { SquareAccordion } from "@/components/loading-ui/square-accordion";
```
```tsx
```
## Customization [#customization]
Use `size`, `blocks`, and `track` for the grid shape, and tune `--duration`,
`--delay`, and `--mask-color` for motion and surface matching.
### Size [#size]
Increase the grid cells and text scale for larger square loaders.
### Color [#color]
Apply text color utilities to recolor both the track and trail.
### Duration [#duration]
Set `--duration` to change the travel-and-pause cycle.
### Glyphs [#glyphs]
Swap the track and moving blocks, and set `--mask-color` for non-default
surfaces.
# Square Grid (/docs/components/square-grid)
`SquareGrid` renders a monospace square track and masks the moving glyphs against
the current surface. The grid size is configurable while the animation stays in
`ch` units.
Credits to [shaah1d](https://x.com/shaah1d) for creating the initial animation.
## Installation [#installation]
Command
Manual
```bash
npx shadcn@latest add @loading-ui/square-grid
```
Copy and paste the following code into your project.
Update the import paths to match your project setup.
## Usage [#usage]
```tsx
import { SquareGrid } from "@/components/loading-ui/square-grid";
```
```tsx
```
## Customization [#customization]
Use `size` for the number of cells per side, `blocks` and `track` for unicode
characters, and `--duration`, `--delay`, or `--mask-color` for timing and
surface matching.
### Size [#size]
Change both text scale and the number of grid cells.
### Color [#color]
The track and moving glyphs inherit foreground color.
### Duration [#duration]
Set `--duration` for slower or faster square travel.
### Glyphs [#glyphs]
Use alternate glyphs and provide `--mask-color` on tinted surfaces.
# Square Snake (/docs/components/square-snake)
`SquareSnake` traces the square path with delayed unicode glyphs instead of a
separate static track, which makes it useful on dense or colored surfaces.
Credits to [shaah1d](https://x.com/shaah1d) for creating the initial animation.
## Installation [#installation]
Command
Manual
```bash
npx shadcn@latest add @loading-ui/square-snake
```
Copy and paste the following code into your project.
Update the import paths to match your project setup.
## Usage [#usage]
```tsx
import { SquareSnake } from "@/components/loading-ui/square-snake";
```
```tsx
```
## Customization [#customization]
Use `size` for the square path, `blocks` for the four moving glyphs, and
`--duration` or `--delay` for animation timing.
### Size [#size]
Change the path cell count and text scale together.
### Color [#color]
The snake inherits foreground color.
### Duration [#duration]
Set `--duration` to tune the loop speed.
### Glyphs [#glyphs]
Provide four glyphs to change the lead, trail, and final tail character.
# Swirling (/docs/components/swirling)
## Installation [#installation]
Command
Manual
```bash
npx shadcn@latest add @loading-ui/swirling
```
Copy and paste the following code into your project.
Update the import paths to match your project setup.
## Usage [#usage]
```tsx
import { Swirling } from "@/components/loading-ui/swirling";
```
```tsx
```
## Customization [#customization]
`Swirling` is one of the more expressive loaders in the set. It works best when you want motion to feel visible and intentional rather than quietly backgrounded, so the most useful adjustments are the ones that shift its visual weight and character directly.
### Size [#size]
Use `size-*` utilities to move the spinner between compact control states and larger featured loading surfaces.
### Color [#color]
The stroke uses `currentColor`, which makes it straightforward to align with accent colors, muted surfaces, or stronger brand moments.
### Stroke Width [#stroke-width]
Changing the stroke width noticeably affects how bold or airy the swirl feels, especially at larger sizes.
### Line Cap [#line-cap]
Adjusting the stroke line cap changes the overall texture of the motion, from softer rounded edges to a sharper mechanical look.
## Examples [#examples]
These examples lean into the more expressive side of `Swirling`. It usually works best in higher-visibility states where a bit of motion helps anchor attention instead of disappearing into the background.
### Button [#button]
Use `Swirling` in buttons when the action is central enough that the pending state should feel active and noticeable.
### Collapsible [#collapsible]
Inside a collapsible task summary, the loader can signal that detailed work is still progressing while the rest of the panel remains explorable.
### Alert [#alert]
For long-running system work that deserves a stronger presence than a minimal spinner, `Swirling` gives the alert a more animated focal point.
### Empty [#empty]
In section-level loading states, the swirl has enough motion and visual mass to hold the layout on its own.
# Symmetric Wave (/docs/components/symmetric-wave)
`SymmetricWave` keeps the source page's mirrored opacity timeline while exposing
the visible block and background track glyphs as props.
Credits to [shaah1d](https://x.com/shaah1d) for creating the initial animation.
## Installation [#installation]
Command
Manual
```bash
npx shadcn@latest add @loading-ui/symmetric-wave
```
Copy and paste the following code into your project.
Update the import paths to match your project setup.
## Usage [#usage]
```tsx
import { SymmetricWave } from "@/components/loading-ui/symmetric-wave";
```
```tsx
```
## Customization [#customization]
Use `block` and `track` for the glyphs. The component inherits text color and
accepts `--duration` for the opacity wave timing.
### Size [#size]
Scale the wave with text-size utilities.
### Color [#color]
Color comes from `currentColor`, so text utilities are the main control.
### Duration [#duration]
Set `--duration` to change how quickly the mirrored wave collapses and expands.
### Glyphs [#glyphs]
Replace the leading block and static track independently.
# Terminal (/docs/components/terminal)
`Terminal` renders a monospace prompt with a blinking block cursor. It is built
for developer-facing UI: command runners, deploy logs, local agents, test jobs,
and any surface where CLI language is already part of the product.
## Installation [#installation]
Command
Manual
```bash
npx shadcn@latest add @loading-ui/terminal
```
Copy and paste the following code into your project.
Update the import paths to match your project setup.
## Usage [#usage]
```tsx
import { Terminal } from "@/components/loading-ui/terminal";
```
```tsx
```
## Customization [#customization]
`Terminal` is intentionally small: the prompt and cursor inherit text color, and
the cursor blink can be tuned with a CSS time value.
### Prompt [#prompt]
Use the prompt that matches your command surface.
### Color [#color]
The prompt and cursor inherit `currentColor`, so contextual foreground utilities
are enough.
### Duration [#duration]
Set `--duration` to speed up or slow down the block cursor blink.
## Examples [#examples]
These examples keep the component close to CLI states instead of using it as a
generic spinner.
### Button [#button]
Buttons work well for command actions that are already running.
### Badge [#badge]
Badges can mark shell, log, or command status without taking much horizontal
space.
### Input Group [#input-group]
Command inputs can use the prompt as a leading addon and text status on the
trailing edge.
### Alert [#alert]
Alerts give command runners enough room to explain what is still happening.
# Text blink (/docs/components/text-blink)
`TextBlink` fades a short line of copy in place. It works best for save states,
temporary connectivity issues, live-edit indicators, and any label that should
stay readable while still showing activity.
## Installation [#installation]
Command
Manual
```bash
npx shadcn@latest add @loading-ui/text-blink
```
Copy and paste the following code into your project.
Update the import paths to match your project setup.
## Usage [#usage]
```tsx
import { TextBlink } from "@/components/loading-ui/text-blink";
```
```tsx
Thinking
```
## Customization [#customization]
`TextBlink` renders as a paragraph by default, but `as="span"` is usually the
right choice inside buttons, badges, and other inline shadcn components.
### Color [#color]
The component inherits text color, so you can style it with normal foreground
utilities.
### Duration [#duration]
Set `--duration` to make the fade feel more urgent or calmer for background saves.
### Opacity [#opacity]
Use `minOpacity` to decide how strongly the text fades at the midpoint.
## Examples [#examples]
These examples keep the blinking copy short and functional. Longer sentences
are harder to read when the full line is fading.
### Button [#button]
Use inline rendering so the animated label sits cleanly inside the button.
### Badge [#badge]
Blinking badges work best for live or autosave states that should remain easy to
scan.
### Alert [#alert]
Alerts are useful when the blinking title needs a short explanation below it.
### Tabs [#tabs]
Tabbed views can isolate active draft or sync states without changing the rest
of the workspace.
# Text dots (/docs/components/text-dots)
`TextDots` appends animated dots to ordinary status copy. It is the lightest
text loader in the set: useful for short waits, inline labels, disabled actions,
and places where a graphic spinner would pull too much attention.
## Installation [#installation]
Command
Manual
```bash
npx shadcn@latest add @loading-ui/text-dots
```
Copy and paste the following code into your project.
Update the import paths to match your project setup.
## Usage [#usage]
```tsx
import { TextDots } from "@/components/loading-ui/text-dots";
```
```tsx
Thinking
```
## Customization [#customization]
`TextDots` keeps your copy as normal text and only animates the appended marks.
Use it when the wording matters more than the animation.
### Color [#color]
The text and dots inherit `currentColor`, so the component works naturally
inside buttons, badges, alerts, and muted helper text.
### Dot Count [#dot-count]
Three dots are the default. Use fewer for very compact labels, or more when the
status should feel a little longer-running.
### Duration [#duration]
Tune `--duration` and `--delay` with CSS time values.
## Examples [#examples]
These examples keep the animation attached to status copy instead of treating it
as a standalone loader.
### Button [#button]
Use `TextDots` when the button label itself is the loading state.
### Badge [#badge]
Status chips stay compact because the animated marks do not need icon space.
### Input Group [#input-group]
Input addons are a natural place for search, generation, and validation copy.
### Alert [#alert]
In alerts, the title can carry the active state while the description explains
what is still happening.
# Text shimmer wave (/docs/components/text-shimmer-wave)
`TextShimmerWave` animates each character through a small shimmer wave. It is
the most expressive text loader, best reserved for assistant-style thinking
states, short generated labels, and places where character-level motion supports
the product language.
## Installation [#installation]
Command
Manual
```bash
npx shadcn@latest add @loading-ui/text-shimmer-wave
```
Copy and paste the following code into your project.
Update the import paths to match your project setup.
## Usage [#usage]
```tsx
import { TextShimmerWave } from "@/components/loading-ui/text-shimmer-wave";
```
```tsx
Thinking
```
## Customization [#customization]
Because every character moves independently, `TextShimmerWave` works best with
short phrases. For longer labels, prefer `TextShimmer`.
### Color [#color]
By default, the resting and active colors are derived from `currentColor`, so
the wave works inside filled buttons and badges. Use `baseColor` and
`shimmerColor` for explicit swatches.
### Duration [#duration]
Shorter durations feel like active thinking; slower durations feel more ambient.
### Motion [#motion]
Tune depth, vertical lift, and rotation when you need the wave to feel subtler
or more expressive.
## Examples [#examples]
These examples keep the wave scoped to short assistant and drafting states so
the moving characters stay readable.
### Button [#button]
Buttons can use wave text as the full action label when the task is generating
or composing.
### Badge [#badge]
Badges are a good fit for compact AI or composing states.
### Alert [#alert]
Use an alert when the wave needs one short sentence of explanation.
### Tabs [#tabs]
Tabs can separate a live reply from sources or supporting material that appears
later.
# Text shimmer (/docs/components/text-shimmer)
`TextShimmer` sweeps a highlight across a line of text. It feels more polished
than dots or blinking, so it is a good fit for generated summaries, AI copy,
document scanning, and premium-feeling loading labels.
## Installation [#installation]
Command
Manual
```bash
npx shadcn@latest add @loading-ui/text-shimmer
```
Copy and paste the following code into your project.
Update the import paths to match your project setup.
## Usage [#usage]
```tsx
import { TextShimmer } from "@/components/loading-ui/text-shimmer";
```
```tsx
Thinking
```
## Customization [#customization]
`TextShimmer` uses a text-clipped gradient. Keep the copy short enough that the
sweep reads as progress instead of becoming a decorative headline.
### Color [#color]
By default, `TextShimmer` derives both colors from `currentColor`, so it follows
filled buttons, badges, and muted text automatically. Use `baseColor` and
`shimmerColor` directly when you need explicit swatches.
### Duration [#duration]
Longer copy usually benefits from a slightly slower sweep.
### Spread [#spread]
`spread` controls how wide the bright part of the sweep becomes.
## Examples [#examples]
These examples use shimmer where the text itself is the loading surface:
generated labels, assistant copy, and scan states.
### Button [#button]
Inside filled buttons, the shimmer follows the button foreground automatically.
### Badge [#badge]
Shimmer badges are useful for generated or indexing states without adding a
separate icon.
### Input Group [#input-group]
Input addons can show that a prompt, query, or answer is being assembled.
### Alert [#alert]
Use alerts when the shimmer headline needs supporting context.
# Triple dot spinner (/docs/components/triple-dot-spinner)
`TripleDotSpinner` rotates three compact markers around their shared center. It
has more motion than a static dot row, but it stays small enough for buttons,
badges, table rows, and local refresh states.
## Installation [#installation]
Command
Manual
```bash
npx shadcn@latest add @loading-ui/triple-dot-spinner
```
Copy and paste the following code into your project.
Update the import paths to match your project setup.
## Usage [#usage]
```tsx
import { TripleDotSpinner } from "@/components/loading-ui/triple-dot-spinner";
```
```tsx
```
## Customization [#customization]
The `size-*` utility controls the dot size, not the whole visual footprint. The
three-dot shape rotates outside that box, so reserve a small fixed slot in
buttons, badges, and table cells.
### Size [#size]
Wrap the spinner in a stable slot, then scale the dots with `size-*`.
### Color [#color]
All three markers use `currentColor`, so the spinner can inherit text color or
use a direct foreground utility.
### Duration [#duration]
Set `--duration` to make the rotation snappier or calmer.
## Examples [#examples]
These examples favor dense surfaces: save buttons, status chips, and compact
alerts where the spinner needs to stay small.
### Button [#button]
A `size-5` icon slot keeps the rotating dots centered without shifting the
button label.
### Badge [#badge]
Use the smallest dot size inside chips so the rotating shape does not crowd the
label.
### Alert [#alert]
Alerts give compact refresh feedback a little more context without blocking the
page.
# Twin orbit (/docs/components/twin-orbit)
`TwinOrbit` is a compact loader built from one center dot and two markers that
orbit in a half-cycle offset. The balanced motion makes it a good fit for
pairing, matching, comparison, replication, or reconciliation states where a
single-direction spinner feels too generic.
## Installation [#installation]
Command
Manual
```bash
npx shadcn@latest add @loading-ui/twin-orbit
```
Copy and paste the following code into your project.
Update the import paths to match your project setup.
## Usage [#usage]
```tsx
import { TwinOrbit } from "@/components/loading-ui/twin-orbit";
```
```tsx
```
## Customization [#customization]
`TwinOrbit` uses `currentColor` and scales from the element size. Because the
orbiting markers travel outside the center dot, leave a little more horizontal
space than the declared `size-*` utility suggests.
### Size [#size]
Small sizes work well inline, while larger dots can anchor compact panel or
status-row loading states.
### Color [#color]
The center and orbiting markers inherit `currentColor`, so color can come from
the surrounding shadcn component or a direct text color utility.
### Duration [#duration]
Set `--duration` to tune the pace. The second marker stays
half a cycle behind so the orbit remains balanced at slower and faster speeds.
# Typing (/docs/components/typing)
## Installation [#installation]
Command
Manual
```bash
npx shadcn@latest add @loading-ui/typing
```
Copy and paste the following code into your project.
Update the import paths to match your project setup.
## Usage [#usage]
```tsx
import { Typing } from "@/components/loading-ui/typing";
```
```tsx
```
## Customization [#customization]
`Typing` animates `translateY` with a short period so each dot feels like it is tapping upward in sequence. Color flows through `bg-current` and inherited foreground. Cycle length is driven by **`--duration`** (default **1s**); delay steps stay at **160ms** per index.
### Size [#size]
Widen the container for calmer motion; keep rows tight next to baseline text.
### Color [#color]
Vivid hex swatches for documentation clarity.
### Duration [#duration]
Faster reads as rapid typing; slower feels more relaxed or “thinking.”
### Dot count [#dot-count]
Match the density of your message chrome; three is the usual chat default.
## Examples [#examples]
Bias examples toward **text and presence**: disabled buttons that mirror chat copy, accordion headers for collaborators, command inputs, and tooltips that explain live editors.
### Button [#button]
Disabled state sells “read-only until idle” without swapping components.
### Badge [#badge]
Great for omnibar, doc header, or thread list chips.
### Accordion [#accordion]
Stack typing motion with a participant list in the panel body.
### Input group [#input-group]
Leading addon slot mirrors command palettes and search-as-you-type rows.
### Tooltip [#tooltip]
Contrast the dots against the tooltip surface with `text-background` when needed.
# Wandering eyes (/docs/components/wandering-eyes)
`WanderingEyes` renders two animated eyes that look around and blink. It works
best for search, discovery, queue watching, and brand-led waiting states where a
standard spinner would feel too mechanical.
## Installation [#installation]
Command
Manual
```bash
npx shadcn@latest add @loading-ui/wandering-eyes
```
Copy and paste the following code into your project.
Update the import paths to match your project setup.
## Usage [#usage]
```tsx
import { WanderingEyes } from "@/components/loading-ui/wandering-eyes";
```
```tsx
```
## Customization [#customization]
`WanderingEyes` uses a container query box with a fixed `9 / 4` aspect ratio.
Set both height and width for predictable layout, inherit color from the
surrounding text, and use `--duration` for the full look-and-blink cycle.
### Size [#size]
Keep the width about 2.25 times the height so the eyes have room to move.
### Color [#color]
By default, the eye shape is a faint version of `currentColor` and the pupil is
solid `currentColor`.
### Color Variables [#color-variables]
Set `--eye-color` and `--pupil-color` when the loader should look more
illustrative than inherited.
### Duration [#duration]
Set `--duration` to make the gaze feel quick and curious or slower and more
ambient.
### Expression [#expression]
Use `eyeScale`, `gapScale`, `pupilScale`, `blinkScale`, and `travelScale` to
tune the expression without editing the component.
# Wave (/docs/components/wave)
## Installation [#installation]
Command
Manual
```bash
npx shadcn@latest add @loading-ui/wave
```
Copy and paste the following code into your project.
Update the import paths to match your project setup.
## Usage [#usage]
```tsx
import { Wave } from "@/components/loading-ui/wave";
```
```tsx
```
## Customization [#customization]
`Wave` uses five fixed bars with different heights, so it reads like audio,
voice, or stream activity instead of a generic progress meter. It inherits
`currentColor`, and the animation can be tuned with `--duration` and `--delay`.
### Size [#size]
Set both height and width. The internal bars use percentages, so the component
stays balanced at compact and larger sizes.
### Color [#color]
The bars use `currentColor`, which makes direct text utilities and inherited
foreground colors enough for most layouts.
### Duration [#duration]
Set `--duration` to make the wave feel quick and responsive or calm and ambient.
### Stagger [#stagger]
Set `--delay` to tighten or loosen the offset between bars.
## Examples [#examples]
These examples use `Wave` for live audio and stream-like states where the shape
adds meaning without needing extra text.
### Button [#button]
Inside buttons, the wave works well when the action is listening, capturing, or
processing a live stream.
### Badge [#badge]
Badges can show live or listening states without taking much space.
### Input Group [#input-group]
Input groups keep voice capture status attached to the field that receives the
result.