shadimage
Beste UI Pieces
componentai11source: ok · hit

Thinking Dots

Three staggered violet-to-fuchsia dots inside a pill next to a Thinking label.

npx shadcn add "https://ui.beste.co/piece/r/ai11.json"
free

No selection tags yet — empty means no evidence, not lack of support.

Dependencies

Bundle weight · light
clsxtailwind-mergelucide-react

Files1 · source cached 10/8/2026, 8:16:12 PM

registry-pieces/ai11/ai11.tsx
"use client";

import { cn } from "@/lib/utils";

type Surface = "card" | "glass";

type Tone =
  | "primary"
  | "foreground"
  | "violet"
  | "emerald"
  | "sky"
  | "amber";

interface Ai11Props {
  label?: string;
  tone?: Tone;
  surface?: Surface;
  bordered?: boolean;
  inverted?: boolean;
  className?: string;
}

const dotClasses: Record<Tone, string> = {
  primary: "bg-primary",
  foreground: "bg-foreground",
  violet: "bg-gradient-to-br from-violet-500 to-fuchsia-500",
  emerald: "bg-gradient-to-br from-emerald-500 to-teal-500",
  sky: "bg-gradient-to-br from-sky-500 to-indigo-500",
  amber: "bg-gradient-to-br from-amber-500 to-orange-500",
};


/* The card sets the colour and everything inside it is drawn in `current`, so
   inverting is two classes rather than a condition on every element.
   `glass` is a deliberate exception to the solid-surface rule: these pieces sit
   over section background images, and a frosted panel is the point of it. */
const surfaceClasses: Record<Surface, { plain: string; inverted: string }> = {
  card: {
    plain: "bg-card text-card-foreground",
    inverted: "bg-foreground text-background",
  },
  glass: {
    plain: "bg-card/60 text-card-foreground backdrop-blur-md",
    inverted: "bg-foreground/60 text-background backdrop-blur-md",
  },
};

export const ai11Demo: Ai11Props = {
  surface: "card",
  bordered: false,
  inverted: false,
  label: "Thinking",
  tone: "primary",
};

export function Ai11({
  label = "Thinking",
  tone = "primary",
  surface = "card",
  bordered = false,
  inverted = false,
  className,
}: Ai11Props) {
  const surfaceTone = surfaceClasses[surface][inverted ? "inverted" : "plain"];

  return (
    <div
      className={cn(
        "relative flex size-full items-center justify-center p-4",
        className
      )}
    >
      <div className={cn("inline-flex items-center gap-2 rounded-full px-3 py-1.5 shadow-sm", surfaceTone, bordered && "border border-current/15")}>
        <div className="flex items-center gap-1" aria-hidden="true">
          {[0, 1, 2].map((i) => (
            <span
              key={i}
              className={cn(
                "size-1.5 animate-pulse rounded-full",
                dotClasses[tone]
              )}
              style={{
                animationDelay: `${i * 180}ms`,
                animationDuration: "1s",
              }}
            />
          ))}
        </div>
        <span className="text-xs font-medium text-current/60">
          {label}
        </span>
      </div>
    </div>
  );
}

More from Beste UI Pieces

Browse all components in this library →