Loader

Small loading indicators for when a reply hasn't started yet, each with an optional label.

Loading preview…

Install

  1. 1

    Run this command in your Tailwind CSS project. It adds components/ai/loader-orb.tsx and installs its dependencies.

    $ npx shadcn@latest add https://gradientdeck.com/ai-components/r/loader-orb.json

Usage & API

Example

loader-orb.tsx
import { LoaderOrb } from "@/components/ai/loader-orb"

<LoaderOrb />

Props LoaderOrb

PropType & descriptionRequired
labelstringOptional
sizenumberOrb diameter in px.Optional
classNamestringOptional

Dependencies

  • React
  • Tailwind CSS
  • motion
Implementation notes

Orb exports LoaderOrb. Props are label, size, default 20, and className. The mark is a round body with a conic gradient of blue, indigo, pink, and sand, a soft glow behind it, and a highlight toward the upper left. It scales slightly while it runs, unless reduced motion is on. The preview centres an unlabelled orb at size 56 and puts the words Thinking… in a sibling span, not in label. A second row uses size 18 and label Reading your files, which is the pattern for a line inside a thread.

Choosing a layout

Use one when the reply has not started and a labelled wait is clearer than an empty bubble. The orb suits a centred pause, or a line such as Reading your files. Dots sit naturally inside a message bubble. Bars suit a job with a duration next to them, such as a transcription. The spinner suits a toolbar or a button that is busy. Pass the label you want the person to read. The component does not rotate through phrases.

Take it away once there is something more specific to show. Reasoning and Chain of thought are that next state: notes, or named steps. A link card that is still fetching its title has its own skeleton inside Link preview, with a sweep across the card, and does not need a second spinner. Do not use a loader as the empty screen of a new chat. That screen is Empty state, which has a greeting, a composer, or a project home, not a status role.

How do I put the spinner on a button without a second colour?

Set tone to current, give the spinner a size that fits the button, and put it in a parent whose text colour is the colour you want. The preview does this on a disabled Saving button: size 14, tone current, and className text-zinc-950 so the arc matches the label. thickness still sets the ring width in pixels. The spectral tone ignores the text colour and always uses the gradient. The label prop is separate. On that button the word Saving is the button's own text, and the spinner has no label, so it exposes Loading to assistive tech.

What should the label say while a chat has no tokens yet?

Say the activity, not a fake percentage. The files use Writing a reply, Reading your files, Transcribing audio, and Running tests. If the mark is decorative next to words you already render, omit label and keep the screen-reader Loading. Do not pass the model's reasoning into label. That text belongs on Reasoning, which takes text and streaming, or on Chain of thought, which takes steps. A loader has no open state and no seconds count.