Agent Steps
spectrumui/agent-stepsFreeBlock
A timeline of tool calls with status, arguments, results, and parallel sub-steps.
Install it
npx shadcn@latest add https://ui.spectrumhq.in/r/agent-steps.jsonSource
1'use client';23import { useState } from 'react';4import { Check, ChevronDown, CircleDashed, X } from 'lucide-react';5import { cn } from '@/lib/utils';67const KEYFRAMES = `8@keyframes su-pop { 0% { opacity: 0; transform: scale(0.85) } 100% { opacity: 1; transform: none } }9`;10import type { ToolCall, ToolCallStatus } from './types';1112const STATUS_STYLES: Record<ToolCallStatus, string> = {13 pending: 'bg-neutral-300 dark:bg-neutral-600',14 running: 'bg-sky-500/80 motion-safe:animate-pulse',15 success: 'bg-emerald-500/80',16 error: 'bg-red-500/80',17 cancelled: 'bg-neutral-400 dark:bg-neutral-500',18};1920export type AgentStepsVariant = 'Default' | 'Compact';2122export interface AgentStepsProps {23 steps: ToolCall[];24 variant?: AgentStepsVariant;25 className?: string;26}2728function duration(step: ToolCall) {29 if (!step.startedAt || !step.completedAt) return null;30 return `${((step.completedAt - step.startedAt) / 1000).toFixed(1)}s`;31}3233export function AgentSteps({ steps, variant = 'Default', className }: AgentStepsProps) {34 return (35 <ol className={cn('w-full max-w-[480px] text-[13px]', className)}>36 <style dangerouslySetInnerHTML={{ __html: KEYFRAMES }} />37 {steps.map((step, index) => (38 <StepRow39 key={step.id}40 step={step}41 last={index === steps.length - 1}42 compact={variant === 'Compact'}43 />44 ))}45 </ol>46 );47}4849function StepRow({ step, last, compact }: { step: ToolCall; last: boolean; compact: boolean }) {50 const [open, setOpen] = useState(false);51 const elapsed = duration(step);52 const expandable = !compact && Boolean(step.result || step.children?.length);5354 return (55 <li className="relative flex gap-3">56 <div className="flex flex-col items-center">57 <span className="grid size-5 shrink-0 place-items-center">58 {step.status === 'success' ? (59 <span className="grid size-4 place-items-center rounded-full bg-emerald-500/15 text-emerald-600 motion-safe:animate-[su-pop_200ms_cubic-bezier(0.23,1,0.32,1)_both] dark:text-emerald-400">60 <Check className="size-2.5" strokeWidth={3} />61 </span>62 ) : step.status === 'error' ? (63 <span className="grid size-4 place-items-center rounded-full bg-red-500/15 text-red-600 motion-safe:animate-[su-pop_200ms_cubic-bezier(0.23,1,0.32,1)_both] dark:text-red-400">64 <X className="size-2.5" strokeWidth={3} />65 </span>66 ) : step.status === 'pending' ? (67// … truncated
What it pulls in
npm packages
Files it writes
More from spectrumui
All 182 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Agent Planagent-plan | spectrumui | Blocks | Free | 1 dep | |
| Approval Cardapproval-card | spectrumui | Blocks | Free | 1 dep | |
| Chat Empty Statechat-empty-state | spectrumui | Blocks | Free | 1 dep · 2 files | |
| Citation Sourcescitation-sources | spectrumui | Blocks | Free | no deps · 2 files | |
| Code Blockcode-block | spectrumui | Blocks | Free | 1 dep | |
| Conversation Listconversation-list | spectrumui | Blocks | Free | 1 dep | |
| Diff Viewdiff-view | spectrumui | Blocks | Free | 1 dep | |
| Error Stateerror-state | spectrumui | Blocks | Free | 1 dep |
