{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "queue",
  "title": "Queue",
  "author": "Jamie Thompson <jamie@jamiethompson.design> (https://jamiethompson.design)",
  "description": "Queued work panel for agent chat: collapsible sections with a count label, a scrollable list of items with a status indicator, strike-through completed state, a description line, image and file attachments, and action buttons revealed on hover, keyboard focus, or always on coarse pointers. Use it for pending todos and queued messages beside a prompt input. Composes shadcn collapsible, scroll-area and button; exports QueueTodo, QueueMessage and QueueMessagePart types.",
  "dependencies": [
    "cn",
    "lucide-react"
  ],
  "registryDependencies": [
    "button",
    "collapsible",
    "scroll-area"
  ],
  "files": [
    {
      "path": "registry/ai/queue.tsx",
      "content": "// Derived from Vercel AI Elements queue.tsx (Apache-2.0, Copyright 2023 Vercel, Inc.).\n// Modified for uifiles: ported from Radix UI to Base UI; dependencies point at @uifiles.\n\"use client\"\n\nimport { cn } from \"cn\"\nimport { ChevronDownIcon, PaperclipIcon } from \"lucide-react\"\nimport type { ComponentProps, ReactNode } from \"react\"\nimport { Button } from \"@/components/ui/button\"\nimport {\n  Collapsible,\n  CollapsibleContent,\n  CollapsibleTrigger,\n} from \"@/components/ui/collapsible\"\nimport { ScrollArea } from \"@/components/ui/scroll-area\"\n\nexport interface QueueMessagePart {\n  type: string\n  text?: string | undefined\n  url?: string | undefined\n  filename?: string | undefined\n  mediaType?: string | undefined\n}\n\nexport interface QueueMessage {\n  id: string\n  parts: QueueMessagePart[]\n}\n\nexport interface QueueTodo {\n  id: string\n  title: string\n  description?: string | undefined\n  status?: \"pending\" | \"completed\" | undefined\n}\n\nexport type QueueItemProps = ComponentProps<\"li\">\n\nexport const QueueItem = ({ className, ...props }: QueueItemProps) => (\n  <li\n    className={cn(\n      \"group flex flex-col gap-1 rounded-md px-3 py-1 text-sm transition-colors hover:bg-muted\",\n      className\n    )}\n    {...props}\n  />\n)\n\nexport type QueueItemIndicatorProps = ComponentProps<\"span\"> & {\n  completed?: boolean | undefined\n}\n\nexport const QueueItemIndicator = ({\n  completed = false,\n  className,\n  ...props\n}: QueueItemIndicatorProps) => (\n  <span\n    className={cn(\n      // uifiles: a full-alpha border so the dot clears 3:1 (upstream's /50 and\n      // /20 borders measure 2.04:1 and 1.30:1); done is filled, pending hollow.\n      \"mt-0.5 inline-block size-2.5 rounded-full border border-muted-foreground\",\n      completed && \"bg-muted-foreground\",\n      className\n    )}\n    {...props}\n  />\n)\n\nexport type QueueItemContentProps = ComponentProps<\"span\"> & {\n  completed?: boolean | undefined\n}\n\nexport const QueueItemContent = ({\n  children,\n  completed = false,\n  className,\n  ...props\n}: QueueItemContentProps) => (\n  <span\n    className={cn(\n      // uifiles: two lines, not upstream's one, so a phone-width title is not\n      // cut off after a few words (the title is the item's only content).\n      \"line-clamp-2 grow break-words\",\n      completed\n        ? \"text-muted-foreground line-through\"\n        : \"text-muted-foreground\",\n      className\n    )}\n    // uifiles: the clamp can still hide a line (a long title, or WCAG 1.4.12\n    // text spacing widening one that fit); the title shows it whole on hover.\n    title={typeof children === \"string\" ? children : undefined}\n    {...props}\n  >\n    {children}\n  </span>\n)\n\nexport type QueueItemDescriptionProps = ComponentProps<\"div\"> & {\n  completed?: boolean | undefined\n}\n\nexport const QueueItemDescription = ({\n  completed = false,\n  className,\n  ...props\n}: QueueItemDescriptionProps) => (\n  <div\n    className={cn(\n      \"ml-6 text-xs\",\n      completed\n        ? \"text-muted-foreground line-through\"\n        : \"text-muted-foreground\",\n      className\n    )}\n    {...props}\n  />\n)\n\nexport type QueueItemActionsProps = ComponentProps<\"div\">\n\nexport const QueueItemActions = ({\n  className,\n  ...props\n}: QueueItemActionsProps) => (\n  <div className={cn(\"flex gap-1\", className)} {...props} />\n)\n\nexport type QueueItemActionProps = Omit<\n  ComponentProps<typeof Button>,\n  \"variant\" | \"size\"\n>\n\nexport const QueueItemAction = ({\n  className,\n  ...props\n}: QueueItemActionProps) => (\n  <Button\n    className={cn(\n      // uifiles: hover-revealed upstream; also revealed on keyboard focus so a\n      // Tab stop is never invisible (WCAG 2.4.7), and always on a coarse\n      // pointer, where Tailwind's hover variant (gated on hover: hover) never\n      // matches and there is no Tab key.\n      \"size-auto rounded p-1 text-muted-foreground opacity-0 transition-opacity group-focus-within:opacity-100 group-hover:opacity-100 hover:bg-muted-foreground/10 hover:text-foreground focus-visible:opacity-100 pointer-coarse:opacity-100\",\n      className\n    )}\n    size=\"icon\"\n    type=\"button\"\n    variant=\"ghost\"\n    {...props}\n  />\n)\n\nexport type QueueItemAttachmentProps = ComponentProps<\"div\">\n\nexport const QueueItemAttachment = ({\n  className,\n  ...props\n}: QueueItemAttachmentProps) => (\n  <div className={cn(\"mt-1 flex flex-wrap gap-2\", className)} {...props} />\n)\n\nexport type QueueItemImageProps = ComponentProps<\"img\">\n\nexport const QueueItemImage = ({\n  className,\n  ...props\n}: QueueItemImageProps) => (\n  // biome-ignore lint/performance/noImgElement: registry source is framework-agnostic; upstream renders a plain img\n  <img\n    alt=\"\"\n    className={cn(\"h-8 w-8 rounded border object-cover\", className)}\n    height={32}\n    width={32}\n    {...props}\n  />\n)\n\nexport type QueueItemFileProps = ComponentProps<\"span\">\n\nexport const QueueItemFile = ({\n  children,\n  className,\n  ...props\n}: QueueItemFileProps) => (\n  <span\n    className={cn(\n      \"flex items-center gap-1 rounded border bg-muted px-2 py-1 text-xs\",\n      className\n    )}\n    // uifiles: the name truncates at 100px; the title shows it whole on hover.\n    title={typeof children === \"string\" ? children : undefined}\n    {...props}\n  >\n    <PaperclipIcon size={12} />\n    <span className=\"max-w-[100px] truncate\">{children}</span>\n  </span>\n)\n\nexport type QueueListProps = ComponentProps<typeof ScrollArea>\n\nexport const QueueList = ({\n  children,\n  className,\n  ...props\n}: QueueListProps) => (\n  <ScrollArea className={cn(\"mt-2 -mb-1\", className)} {...props}>\n    <div className=\"max-h-40 pr-4\">\n      <ul>{children}</ul>\n    </div>\n  </ScrollArea>\n)\n\n// QueueSection - collapsible section container\nexport type QueueSectionProps = ComponentProps<typeof Collapsible>\n\nexport const QueueSection = ({\n  className,\n  defaultOpen = true,\n  ...props\n}: QueueSectionProps) => (\n  <Collapsible className={cn(className)} defaultOpen={defaultOpen} {...props} />\n)\n\n// QueueSectionTrigger - section header/trigger\nexport type QueueSectionTriggerProps = ComponentProps<\"button\">\n\nexport const QueueSectionTrigger = ({\n  children,\n  className,\n  ...props\n}: QueueSectionTriggerProps) => (\n  <CollapsibleTrigger\n    className={cn(\n      \"group flex w-full items-center justify-between rounded-md bg-muted/40 px-3 py-2 text-left text-sm font-medium text-muted-foreground transition-colors hover:bg-muted\",\n      className\n    )}\n    type=\"button\"\n    {...props}\n  >\n    {children}\n  </CollapsibleTrigger>\n)\n\n// QueueSectionLabel - label content with icon and count\nexport type QueueSectionLabelProps = ComponentProps<\"span\"> & {\n  count?: number | undefined\n  label: string\n  icon?: ReactNode | undefined\n}\n\nexport const QueueSectionLabel = ({\n  count,\n  label,\n  icon,\n  className,\n  ...props\n}: QueueSectionLabelProps) => (\n  <span className={cn(\"flex items-center gap-2\", className)} {...props}>\n    <ChevronDownIcon className=\"size-4 -rotate-90 transition-transform group-data-panel-open:rotate-0\" />\n    {icon}\n    <span>\n      {count} {label}\n    </span>\n  </span>\n)\n\n// QueueSectionContent - collapsible content area\nexport type QueueSectionContentProps = ComponentProps<typeof CollapsibleContent>\n\nexport const QueueSectionContent = ({\n  className,\n  ...props\n}: QueueSectionContentProps) => (\n  <CollapsibleContent className={cn(className)} {...props} />\n)\n\nexport type QueueProps = ComponentProps<\"div\">\n\nexport const Queue = ({ className, ...props }: QueueProps) => (\n  <div\n    className={cn(\n      \"flex flex-col gap-2 rounded-xl border border-border bg-background px-3 pt-2 pb-2 shadow-xs\",\n      className\n    )}\n    {...props}\n  />\n)\n",
      "type": "registry:component",
      "target": "components/ai/queue.tsx"
    }
  ],
  "docs": "Derived from Vercel AI Elements (Apache-2.0, Copyright 2023 Vercel, Inc.); ported to Base UI and maintained by uifiles. Built for the Base UI styles (base-nova): it composes the Base UI wrappers from components/ui and relies on their render prop and event signatures, so it does not work on Radix or React Aria styles. Base UI port of AI Elements queue. QueueSectionTrigger is the Collapsible trigger's own native <button> (upstream wrapped a <button> in asChild); its chevron rotates on the trigger's data-panel-open attribute. QueueSectionContent unmounts when closed (Base UI Panel default; pass keepMounted to retain). QueueList is a Base UI ScrollArea, so Radix `type` and `scrollHideDelay` props do not exist. onOpenChange receives (open, eventDetails). Contrast changes: completed items use full-alpha text-muted-foreground with line-through instead of upstream's 50% and 40% alpha, which fail AA; QueueItemIndicator uses a full-alpha border-muted-foreground (pending hollow, completed filled with bg-muted-foreground) instead of upstream's 50% and 20% borders, which fall below 3:1. QueueItemAction is revealed on row hover, on keyboard focus (focus-visible and group-focus-within), and always on coarse pointers (pointer-coarse:opacity-100), because Tailwind gates the hover variant on (hover: hover) and a phone has neither hover nor a Tab key. QueueItemContent clamps titles to two lines (upstream one) so a phone-width title is not cut off after a few words; the clamp cuts whole lines. QueueItemFile truncates the file name at 100px. Both the chip and the item title mirror the whole text in a title attribute when their children are a string (your own title wins), so a truncated file name, or a title that WCAG 1.4.12 text spacing pushes onto a third line, stays readable on hover.",
  "categories": [
    "ai",
    "chat",
    "agent"
  ],
  "type": "registry:component"
}