flohoeller

Thinking Loader

AI chats 10

About

A small working pill for AI replies – an eight-ray spinner and a shimmering label that rolls through phases and settles on a check. From affectUI (affectui.com).

Built with React and Tailwind. Copy the prompt and paste it into Claude Code, Cursor or Lovable: your agent adds Thinking Loader to your project and fits it to your theme.

Code

How Thinking Loader is used: the demo's code. The component's own source comes with a free account.

Usage.tsx

import { useEffect, useState } from "react";
import { ThinkingLoader } from "@/components/ui/thinking-loader";

const PHASES = ["Thinking", "Searching the web", "Reading 12 sources", "Comparing pricing", "Writing response"];
const INTERVAL = 2000;
const HOLD = 2600;

// Walks through the phases, finishes, holds the check for a moment and starts over
export default function Demo() {
  const [run, setRun] = useState(0);
  const [done, setDone] = useState(false);

  useEffect(() => {
    const finish = window.setTimeout(() => setDone(true), PHASES.length * INTERVAL);
    const again = window.setTimeout(() => {
      setDone(false);
      setRun((r) => r + 1);
    }, PHASES.length * INTERVAL + HOLD);
    return () => {
      window.clearTimeout(finish);
      window.clearTimeout(again);
    };
  }, [run]);

  return (
    <div className="tl-demo">
      <style>{demoCss}</style>
      <div className="tl-demo__chat">
        <p className="tl-demo__you">Which CRM fits a 10-person sales team best?</p>
        <ThinkingLoader key={run} phases={PHASES} interval={INTERVAL} done={done} />
      </div>
    </div>
  );
}

const demoCss = `
.tl-demo {
  display: grid;
  grid-template-columns: minmax(0, 420px);
  place-content: center;
  width: 100%;
  font-family: "Inter", ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
}
.tl-demo__chat {
  display: grid;
  justify-items: start;
  gap: 18px;
  min-width: 0;
}
.tl-demo__you {
  justify-self: end;
  max-width: 88%;
  margin: 0;
  padding: 10px 14px;
  border-radius: 18px 18px 6px 18px;
  background: #f0f0f0;
  color: #171717;
  font-size: 14px;
  line-height: 1.45;
}
:where(.dark, [data-theme="dark"]) .tl-demo__you { background: #262628; color: #ededed; }

/* Library cards: just the pill, a little larger and dead center (the question would push it off-center) */
.card__preview .tl-demo {
  position: absolute;
  inset: 0;
  grid-template-columns: auto;
  place-content: center;
  padding-top: 20px;
}
.card__preview .tl-demo__you { display: none; }
.card__preview .tl-demo__chat { justify-items: center; zoom: 1.25; }

/* A fixed stage – only the pill changes width */
.stage:has(.tl-demo) { height: 420px; }
@media (max-width: 760px) {
  .stage:has(.tl-demo) { height: 380px; padding-left: 16px; padding-right: 16px; }
}

/* Clean style: the question bubble in the clean type scale */
.tl-demo--clean .tl-demo__you {
  padding: 8px 12px;
  border-radius: 10px 10px 4px 10px;
  background: rgba(0, 0, 0, 0.04);
  color: rgba(0, 0, 0, 0.88);
  font-size: 13px;
  line-height: 20px;
}
:where(.dark, [data-theme="dark"]) .tl-demo--clean .tl-demo__you { background: rgba(255, 255, 255, 0.08); color: rgba(255, 255, 255, 0.9); }
`;

More by flohoeller

View all
  • Message Actions

    Message Actions

    10
  • Tool Call Card

    Tool Call Card

  • OTP Input

    OTP Input

  • Segmented Control

    Segmented Control

More in AI chats

View all
  • AI Actions

    AI Actions

    324
  • Message Thread

    Message Thread

    42
  • Color Picker

    Color Picker

    99
  • Environment Variables

    Environment Variables

    13
  • Approval Card

    Approval Card

    16
  • AI Task List

    AI Task List

    165
  • Agent Chat

    Agent Chat

    18
  • System Message

    System Message

    57