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 · lightclsxtailwind-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>
);
}