{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "task-rows",
  "title": "Task Rows",
  "description": "Live agent task rows with status badges and expandable notes.",
  "dependencies": [
    "lucide-react"
  ],
  "files": [
    {
      "path": "components/spectrumui/blocks/ai-assistants/task-rows.tsx",
      "content": "'use client';\n\nimport { useState } from 'react';\nimport { Check, ChevronDown, CircleDashed, Loader2, X } from 'lucide-react';\nimport { cn } from '@/lib/utils';\n\nconst KEYFRAMES = `\n@keyframes su-pop { 0% { opacity: 0; transform: scale(0.85) } 100% { opacity: 1; transform: none } }\n`;\n\nexport type TaskStatus = 'queued' | 'running' | 'completed' | 'failed';\n\nexport interface TaskRow {\n  id: string;\n  title: string;\n  detail?: string;\n  status: TaskStatus;\n  note?: string;\n}\n\nexport type TaskRowsVariant = 'Default' | 'Compact';\n\nexport interface TaskRowsProps {\n  tasks: TaskRow[];\n  variant?: TaskRowsVariant;\n  className?: string;\n}\n\nconst BADGE: Record<TaskStatus, string> = {\n  queued: 'bg-black/[0.05] text-neutral-500 dark:bg-white/[0.07] dark:text-neutral-400',\n  running: 'bg-sky-500/10 text-sky-700 dark:text-sky-400',\n  completed: 'bg-emerald-500/10 text-emerald-700 dark:text-emerald-400',\n  failed: 'bg-red-500/10 text-red-700 dark:text-red-400',\n};\n\nfunction StatusIcon({ status }: { status: TaskStatus }) {\n  if (status === 'completed')\n    return (\n      <span className=\"grid size-5 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\">\n        <Check className=\"size-3\" strokeWidth={3} />\n      </span>\n    );\n  if (status === 'failed')\n    return (\n      <span className=\"grid size-5 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\">\n        <X className=\"size-3\" strokeWidth={3} />\n      </span>\n    );\n  if (status === 'running')\n    return (\n      <Loader2 className=\"size-4 animate-spin text-sky-600 [animation-duration:800ms] motion-reduce:animate-none dark:text-sky-400\" />\n    );\n  return <CircleDashed className=\"size-4 text-neutral-300 dark:text-neutral-600\" />;\n}\n\nexport function TaskRows({ tasks, variant = 'Default', className }: TaskRowsProps) {\n  const [openId, setOpenId] = useState<string | null>(null);\n  const compact = variant === 'Compact';\n\n  return (\n    <ul\n      className={cn(\n        'w-full max-w-[480px] divide-y divide-black/[0.05] overflow-hidden rounded-2xl border border-black/[0.07] bg-white shadow-xs dark:divide-white/[0.06] dark:border-white/[0.08] dark:bg-[#0B0B0D]',\n        className,\n      )}\n    >\n      <style dangerouslySetInnerHTML={{ __html: KEYFRAMES }} />\n      {tasks.map((task) => {\n        const open = task.id === openId;\n        const expandable = !compact && Boolean(task.note);\n        return (\n          <li key={task.id}>\n            <button\n              type=\"button\"\n              disabled={!expandable}\n              aria-expanded={expandable ? open : undefined}\n              onClick={() => setOpenId(open ? null : task.id)}\n              className={cn(\n                'flex w-full items-center gap-2.5 px-3 text-left',\n                compact ? 'py-2' : 'py-2.5',\n                expandable &&\n                  'transition-colors duration-150 hover:bg-black/[0.02] focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-neutral-400 dark:hover:bg-white/[0.03]',\n              )}\n            >\n              <StatusIcon status={task.status} />\n              <span className=\"min-w-0 flex-1\">\n                <span\n                  className={cn(\n                    'block truncate font-medium text-neutral-800 dark:text-neutral-200',\n                    compact ? 'text-[12.5px]' : 'text-[13px]',\n                  )}\n                >\n                  {task.title}\n                </span>\n              </span>\n              {task.detail && (\n                <span className=\"shrink-0 font-mono text-[10.5px] tabular-nums text-neutral-400 dark:text-neutral-600\">\n                  {task.detail}\n                </span>\n              )}\n              <span\n                className={cn(\n                  'shrink-0 rounded-full px-2 py-0.5 font-mono text-[9.5px] font-medium uppercase tracking-wide',\n                  BADGE[task.status],\n                )}\n              >\n                {task.status}\n              </span>\n              {expandable && (\n                <ChevronDown\n                  className={cn(\n                    'size-3 shrink-0 text-neutral-400 transition-transform duration-200 ease-[cubic-bezier(0.23,1,0.32,1)]',\n                    open && 'rotate-180',\n                  )}\n                />\n              )}\n            </button>\n\n            {expandable && (\n              <div\n                className=\"grid transition-[grid-template-rows] duration-[240ms] ease-[cubic-bezier(0.32,0.72,0,1)]\"\n                style={{ gridTemplateRows: open ? '1fr' : '0fr' }}\n              >\n                <div className=\"overflow-hidden\">\n                  <p className=\"px-3 pb-3 pl-[42px] text-[12px] leading-[1.6] text-neutral-500 dark:text-neutral-400\">\n                    {task.note}\n                  </p>\n                </div>\n              </div>\n            )}\n          </li>\n        );\n      })}\n    </ul>\n  );\n}\n\nexport default TaskRows;\n",
      "type": "registry:block",
      "target": "components/spectrumui/blocks/ai-assistants/task-rows.tsx"
    }
  ],
  "type": "registry:block"
}
