| 1 | "use client"; |
| 2 | |
| 3 | import { type ReactNode } from "react"; |
| 4 | |
| 5 | import { cn } from "@/lib/utils"; |
| 6 | |
| 7 | import { Brain } from "./icons"; |
| 8 | import { TextShimmer } from "./text-shimmer"; |
| 9 | |
| 10 | interface AILoadingLabelProps { |
| 11 | label?: string; |
| 12 | icon?: ReactNode; |
| 13 | className?: string; |
| 14 | iconClassName?: string; |
| 15 | textClassName?: string; |
| 16 | duration?: number; |
| 17 | spread?: number; |
| 18 | } |
| 19 | |
| 20 | export function AILoadingLabel({ |
| 21 | label = "AI is thinking", |
| 22 | icon, |
| 23 | className, |
| 24 | iconClassName, |
| 25 | textClassName, |
| 26 | duration = 1.6, |
| 27 | spread = 2.25, |
| 28 | }: AILoadingLabelProps) { |
| 29 | return ( |
| 30 | <div className={cn("flex items-center gap-2 text-sm", className)}> |
| 31 | <span |
| 32 | className={cn("flex shrink-0 items-center justify-center", iconClassName)} |
| 33 | > |
| 34 | {icon ?? <Brain className="h-4 w-4 animate-pulse text-primary" />} |
| 35 | </span> |
| 36 | <TextShimmer |
| 37 | as="span" |
| 38 | duration={duration} |
| 39 | spread={spread} |
| 40 | className={cn( |
| 41 | "font-semibold [--base-color:hsl(var(--muted-foreground))] [--base-gradient-color:hsl(var(--primary))] dark:[--base-color:hsl(var(--muted-foreground))] dark:[--base-gradient-color:hsl(var(--foreground))]", |
| 42 | textClassName, |
| 43 | )} |
| 44 | > |
| 45 | {label} |
| 46 | </TextShimmer> |
| 47 | </div> |
| 48 | ); |
| 49 | } |
| 50 |