All files / components/chat loading-indicator.tsx

0% Statements 0/11
0% Branches 0/7
0% Functions 0/3
0% Lines 0/11

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69                                                                                                                                         
import { APP_NAME } from "@/constants/app";
import { Avatar } from "@/components/ui/avatar";
import { Card } from "@/components/ui/card";
import { Skeleton } from "@/components/ui/skeleton";
import { cn } from "@/utils/class-name";
 
const SKELETON_WIDTHS = ["w-full", "w-4/5", "w-3/5"] as const;
const DOT_DELAYS = ["0ms", "150ms", "300ms"] as const;
 
type LoadingIndicatorProps = {
  showAvatar?: boolean;
  label?: string;
  className?: string;
};
 
export function LoadingIndicator({
  showAvatar = true,
  label,
  className,
}: LoadingIndicatorProps) {
  const headerLabel = label?.trim() || "Thinking";
 
  return (
    <article
      className={cn(
        "flex items-start gap-2.5 py-1",
        !showAvatar && "gap-0 py-0",
        className,
      )}
    >
      {showAvatar ? (
        <Avatar variant="assistant" size="sm" className="mt-0.5" />
      ) : null}
 
      <Card
        variant="glass"
        className="w-[18.75rem] max-w-full border-white/10 bg-glass px-4 py-3.5 shadow-[0_10px_28px_rgba(7,12,30,0.28)]"
      >
        <div className="mb-2.5">
          <span className="font-syne text-sm font-semibold tracking-wide text-white/82">
            {APP_NAME}
          </span>
        </div>
 
        <div className="mb-3 flex items-center gap-1">
          <span className="font-dm-sans text-sm font-medium text-white/68">
            {headerLabel}
          </span>
          <span className="ml-0.5 flex gap-0.5">
            {DOT_DELAYS.map((delay, i) => (
              <span
                key={i}
                className="h-1 w-1 rounded-full bg-white/40 animate-pulse"
                style={{ animationDelay: delay, animationDuration: "1200ms" }}
              />
            ))}
          </span>
        </div>
 
        <div className="flex flex-col gap-2">
          {SKELETON_WIDTHS.map((width, i) => (
            <Skeleton key={i} className={`h-2.5 rounded-full bg-white/9 ${width}`} />
          ))}
        </div>
      </Card>
    </article>
  );
}