{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "elements-elicitation-form",
  "type": "registry:component",
  "title": "Elicitation form",
  "description": "A server pausing mid-tool-call to ask you for the fields it still needs.",
  "registryDependencies": [
    "https://r.assistant-ui.com/elements-surfaces.json"
  ],
  "dependencies": [
    "lucide-react"
  ],
  "files": [
    {
      "type": "registry:component",
      "path": "components/assistant-ui/elements/elicitation-form.tsx",
      "sourcePath": "packages/ui/src/components/react/assistant-ui/elements/elicitation-form.tsx",
      "content": "\"use client\";\n\nimport type { ComponentProps } from \"react\";\nimport { CheckIcon, PlugIcon, XIcon } from \"lucide-react\";\nimport { cn } from \"@/lib/utils\";\nimport { field, inkButton, mono, paper } from \"./surfaces\";\n\nexport type ElicitationState = \"request\" | \"accepted\" | \"declined\";\n\nexport interface ElicitationField {\n  name: string;\n  label: string;\n  value: string;\n  kind: \"text\" | \"choice\" | \"toggle\";\n  options?: readonly string[];\n  required?: boolean;\n}\n\nexport function ElicitationForm({\n  server,\n  message,\n  fields,\n  state,\n  onAccept,\n  onDecline,\n  className,\n  ...props\n}: Omit<\n  ComponentProps<\"div\">,\n  | \"children\"\n  | \"server\"\n  | \"message\"\n  | \"fields\"\n  | \"state\"\n  | \"onAccept\"\n  | \"onDecline\"\n> & {\n  server: string;\n  message: string;\n  fields: readonly ElicitationField[];\n  state: ElicitationState;\n  onAccept?: () => void;\n  onDecline?: () => void;\n}) {\n  return (\n    <div\n      data-slot=\"elicitation-form\"\n      className={cn(\n        paper,\n        \"flex w-full max-w-sm flex-col gap-3.5 rounded-[20px] p-4\",\n        className,\n      )}\n\n      {...props}\n    >\n      <div className=\"flex items-center gap-2.5\">\n        <span className=\"bg-foreground/[0.05] text-foreground/45 flex size-7 shrink-0 items-center justify-center rounded-lg\">\n          <PlugIcon className=\"size-3.5\" />\n        </span>\n        <span className=\"min-w-0 flex-1 truncate text-[13.5px] font-medium\">\n          {server}\n        </span>\n        <span className={cn(mono, \"text-foreground/30 shrink-0\")}>\n          needs input\n        </span>\n      </div>\n\n      <p className=\"text-foreground/55 text-xs leading-relaxed\">{message}</p>\n\n      <div className=\"flex flex-col gap-2.5\">\n        {fields.map((item) => (\n          <div key={item.name} className=\"flex flex-col gap-1\">\n            <span className={cn(mono, \"text-foreground/35\")}>\n              {item.label}\n              {item.required && <span className=\"text-foreground/25\"> *</span>}\n            </span>\n            {item.kind === \"choice\" ? (\n              <div className=\"flex flex-wrap gap-1.5\">\n                {item.options?.map((option) => (\n                  <span\n                    key={option}\n                    className={cn(\n                      \"rounded-full px-2.5 py-1 text-xs transition-colors\",\n                      option === item.value\n                        ? \"bg-foreground text-background\"\n                        : cn(field, \"text-foreground/55\"),\n                    )}\n                  >\n                    {option}\n                  </span>\n                ))}\n              </div>\n            ) : item.kind === \"toggle\" ? (\n              <span className=\"flex items-center gap-2\">\n                <span\n                  aria-hidden\n                  className={cn(\n                    \"flex h-4 w-7 items-center rounded-full p-0.5 transition-colors duration-200\",\n                    item.value === \"true\"\n                      ? \"bg-foreground/80\"\n                      : \"bg-foreground/15\",\n                  )}\n                >\n                  <span\n                    className={cn(\n                      \"bg-background size-3 rounded-full transition-transform duration-200 motion-reduce:transition-none\",\n                      item.value === \"true\" && \"translate-x-3\",\n                    )}\n                  />\n                </span>\n                <span className=\"text-foreground/55 text-xs\">\n                  {item.value === \"true\" ? \"On\" : \"Off\"}\n                </span>\n              </span>\n            ) : (\n              <span\n                className={cn(\n                  field,\n                  \"text-foreground/80 rounded-lg px-2.5 py-1.5 text-xs\",\n                )}\n              >\n                {item.value}\n              </span>\n            )}\n          </div>\n        ))}\n      </div>\n\n      <div className=\"flex h-8 items-center justify-end gap-2\">\n        {state === \"request\" ? (\n          <>\n            <button\n              type=\"button\"\n              onClick={onDecline}\n              className=\"text-foreground/55 hover:bg-foreground/[0.06] hover:text-foreground/90 h-8 rounded-full px-3.5 text-xs font-medium transition-[background-color,color,scale] duration-150 active:scale-[0.96]\"\n            >\n              Decline\n            </button>\n            <button\n              type=\"button\"\n              onClick={onAccept}\n              className={cn(\n                inkButton,\n                \"flex h-8 items-center rounded-full px-3.5 text-xs font-medium\",\n              )}\n            >\n              Send\n            </button>\n          </>\n        ) : (\n          <span\n            key={state}\n            className=\"fade-in animate-in text-foreground/55 flex items-center gap-2 text-xs duration-300\"\n          >\n            {state === \"accepted\" ? (\n              <>\n                <CheckIcon className=\"size-3.5 text-emerald-500\" />\n                Sent to {server}\n              </>\n            ) : (\n              <>\n                <XIcon className=\"text-foreground/45 size-3.5\" />\n                Declined\n              </>\n            )}\n          </span>\n        )}\n      </div>\n    </div>\n  );\n}\n"
    }
  ]
}