Ai Reasoning
smoothui-registry/ai-reasoningFreeComponent
Collapsible AI reasoning trace that shimmers only while the model works, reports how long it took and gets out of the way.
Install it
npx shadcn@latest add https://www.smoothui.dev/r/ai-reasoning.jsonSource
1"use client";23import { cn } from "@/lib/utils";4import { ChevronRight } from "lucide-react";5import { AnimatePresence, motion, useReducedMotion } from "motion/react";6import { type ReactNode, useEffect, useRef, useState } from "react";78const SPRING_DEFAULT = {9 bounce: 0.1,10 duration: 0.25,11 type: "spring" as const,12};13const EASE_OUT = [0.23, 1, 0.32, 1] as const;14/**15 * A beat before auto-collapsing. Snapping shut the instant the trace finishes16 * makes it feel like the content was yanked away mid-read.17 */18const AUTO_COLLAPSE_DELAY_MS = 600;19const MS_PER_SECOND = 1000;20const SHIMMER_SECONDS = 1.8;2122export type AIReasoningProps = {23 children: ReactNode;24 className?: string;25 /**26 * Collapse itself once `isStreaming` goes false. The trace is scaffolding —27 * interesting while it happens, clutter once the answer has landed.28 */29 collapseWhenDone?: boolean;30 /** Start expanded. */31 defaultOpen?: boolean;32 /** Seconds the model spent. Omit to have the component time it itself. */33 duration?: number;34 isStreaming?: boolean;35};3637/**38 * Collapsible reasoning trace.39 *40 * The summary line shimmers only while the model is actually working, so the41 * shimmer means something rather than being decoration. When the trace ends it42 * settles, reports how long it took, and gets out of the way.43 */44const AIReasoning = ({45 children,46 className,47 collapseWhenDone = true,48 defaultOpen,49 duration,50 isStreaming = false,51}: AIReasoningProps) => {52 const shouldReduceMotion = useReducedMotion();53 const [isOpen, setIsOpen] = useState(defaultOpen ?? isStreaming);54 // Once someone opens or closes it by hand, stop deciding for them.55 const [isUserControlled, setIsUserControlled] = useState(false);5657 const startedAtRef = useRef<number | null>(null);58 const [measuredSeconds, setMeasuredSeconds] = useState<number | null>(null);5960 useEffect(() => {61 if (isStreaming) {62 startedAtRef.current = Date.now();63 setMeasuredSeconds(null);64 if (!isUserControlled) {65 setIsOpen(true);66 }67 return;68 }69 if (startedAtRef.current !== null) {70 setMeasuredSeconds((Date.now() - startedAtRef.current) / MS_PER_SECOND);71 startedAtRef.current = null;72 }73 }, [isStreaming, isUserControlled]);7475 useEffect(() => {76 if (isStreaming || !collapseWhenDone || isUserControlled) {77 return;78 }79 const timeout = setTimeout(() => setIsOpen(false), AUTO_COLLAPSE_DELAY_MS);80 return () => clearTimeout(timeout);81// … truncated
What it pulls in
npm packages
Files it writes
More from SmoothUI Registry
All 178 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Agent Avataragent-avatar | SmoothUI Registry | Components | Free | no deps | |
| Ai Approvalai-approval | SmoothUI Registry | Components | Free | 2 deps | |
| Ai Artifactai-artifact | SmoothUI Registry | Components | Free | 2 deps | |
| Ai Branchai-branch | SmoothUI Registry | Components | Free | 2 deps | |
| Ai Citationai-citation | SmoothUI Registry | Components | Free | 2 deps | |
| Ai Context Meterai-context-meter | SmoothUI Registry | Components | Free | 2 deps | |
| Ai Conversationai-conversation | SmoothUI Registry | Components | Free | 2 deps | |
| Ai Coreai-core | SmoothUI Registry | Components | Free | 1 dep |
