Tool Chips
spectrumui/tool-chipsFreeBlock
Compact tool-call chips that expand into their arguments and result.
Install it
npx shadcn@latest add https://ui.spectrumhq.in/r/tool-chips.jsonSource
1'use client';23import { useState } from 'react';4import { cn } from '@/lib/utils';5import type { ToolCall, ToolCallStatus } from './types';67const DOT: Record<ToolCallStatus, string> = {8 pending: 'bg-neutral-300 dark:bg-neutral-600',9 running: 'bg-sky-500/80 motion-safe:animate-pulse',10 success: 'bg-emerald-500/80',11 error: 'bg-red-500/80',12 cancelled: 'bg-neutral-400 dark:bg-neutral-500',13};1415export type ToolChipsVariant = 'Row' | 'Stack';1617export interface ToolChipsProps {18 calls: ToolCall[];19 variant?: ToolChipsVariant;20 className?: string;21}2223function duration(call: ToolCall) {24 if (!call.startedAt || !call.completedAt) return null;25 return `${((call.completedAt - call.startedAt) / 1000).toFixed(1)}s`;26}2728export function ToolChips({ calls, variant = 'Row', className }: ToolChipsProps) {29 const [openId, setOpenId] = useState<string | null>(null);30 const open = calls.find((call) => call.id === openId);3132 return (33 <div className={cn('w-full max-w-[480px]', className)}>34 <div className={cn('flex gap-1.5', variant === 'Stack' ? 'flex-col' : 'flex-wrap')}>35 {calls.map((call) => {36 const active = call.id === openId;37 const elapsed = duration(call);38 return (39 <button40 key={call.id}41 type="button"42 aria-expanded={active}43 onClick={() => setOpenId(active ? null : call.id)}44 className={cn(45 'flex items-center gap-2 rounded-lg border py-1.5 pl-2.5 pr-3 text-left',46 'transition-[border-color,background-color,transform] duration-150 active:scale-[0.98]',47 'focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-neutral-400',48 active49 ? 'border-black/[0.16] bg-black/[0.03] dark:border-white/[0.22] dark:bg-white/[0.05]'50 : 'border-black/[0.07] hover:border-black/[0.14] dark:border-white/[0.08] dark:hover:border-white/[0.16]',51 variant === 'Stack' && 'w-full',52 )}53 >54 <span className={cn('size-1.5 shrink-0 rounded-full', DOT[call.status])} />55 <span className="truncate font-mono text-[11.5px] font-medium text-neutral-700 dark:text-neutral-300">56 {call.name}57 </span>58 {call.status === 'running' ? (59 <span className="ml-auto shrink-0 font-mono text-[10px] uppercase tracking-wide text-sky-600 dark:text-sky-400">60// … truncated
Files it writes
More from spectrumui
All 182 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Agent Planagent-plan | spectrumui | Blocks | Free | 1 dep | |
| Agent Stepsagent-steps | spectrumui | Blocks | Free | 1 dep · 2 files | |
| 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 |
