diff --git a/surfsense_web/components/prompt-kit/loader.tsx b/surfsense_web/components/prompt-kit/loader.tsx new file mode 100644 index 000000000..a51876e64 --- /dev/null +++ b/surfsense_web/components/prompt-kit/loader.tsx @@ -0,0 +1,74 @@ +"use client"; + +import { cn } from "@/lib/utils"; + +export interface LoaderProps { + variant?: "text-shimmer"; + size?: "sm" | "md" | "lg"; + text?: string; + className?: string; +} + +const textSizes = { + sm: "text-xs", + md: "text-sm", + lg: "text-base", +} as const; + +/** + * TextShimmerLoader - A text loader with a shimmer gradient animation + * Used for in-progress states in write_todos and chain-of-thought + */ +export function TextShimmerLoader({ + text = "Thinking", + className, + size = "md", +}: { + text?: string; + className?: string; + size?: "sm" | "md" | "lg"; +}) { + return ( + <> + + + {text} + + > + ); +} + +/** + * Loader component - currently only supports text-shimmer variant + * Can be extended with more variants if needed in the future + */ +export function Loader({ + variant = "text-shimmer", + size = "md", + text, + className, +}: LoaderProps) { + switch (variant) { + case "text-shimmer": + default: + return ( + + ); + } +} + diff --git a/surfsense_web/components/tool-ui/plan/plan.tsx b/surfsense_web/components/tool-ui/plan/plan.tsx index 472cc41b8..90ac5c614 100644 --- a/surfsense_web/components/tool-ui/plan/plan.tsx +++ b/surfsense_web/components/tool-ui/plan/plan.tsx @@ -7,7 +7,7 @@ import { PartyPopper, XCircle, } from "lucide-react"; -import type { FC, ReactNode } from "react"; +import type { FC } from "react"; import { useMemo, useState } from "react"; import { Accordion, @@ -18,6 +18,7 @@ import { import { Button } from "@/components/ui/button"; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "@/components/ui/collapsible"; +import { TextShimmerLoader } from "@/components/prompt-kit/loader"; import { Progress } from "@/components/ui/progress"; import { cn } from "@/lib/utils"; import type { Action, ActionsConfig } from "../shared/schema"; @@ -73,24 +74,33 @@ interface TodoItemProps { const TodoItem: FC = ({ todo, isStreaming = true }) => { const isStrikethrough = todo.status === "completed" || todo.status === "cancelled"; - // Only show pulse animation if streaming and in progress + // Only show shimmer animation if streaming and in progress const isShimmer = todo.status === "in_progress" && isStreaming; + // Render the label with optional shimmer effect + const renderLabel = () => { + if (isShimmer) { + return ; + } + return ( + + {todo.label} + + ); + }; + if (todo.description) { return ( - - {todo.label} - + {renderLabel()} @@ -103,15 +113,7 @@ const TodoItem: FC = ({ todo, isStreaming = true }) => { return ( - - {todo.label} - + {renderLabel()} ); };