{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "metal-prompt-bar",
  "title": "Metal Prompt Bar",
  "description": "An AI prompt bar with a live liquid-metal send button that reflects onto the chips beside it.",
  "dependencies": [
    "metal-fx",
    "lucide-react"
  ],
  "registryDependencies": [
    "@spectrumui/use-surface-theme"
  ],
  "files": [
    {
      "path": "components/spectrumui/metal-prompt-bar.tsx",
      "content": "/**\n * Spectrum UI — MetalPromptBar\n *\n * An AI prompt bar whose send button wears a live liquid-metal ring painted by\n * `metal-fx` (Jakub Antalík, MIT, https://metal.jakubantalik.com). The chips\n * beside it are passed to MetalFx as reflection targets, so in dark mode they\n * pick up a soft mirrored glint of the ring — the composer from the metal-fx\n * showcase, wired for React state: auto-growing textarea, Enter to send,\n * Shift+Enter for newlines, and a disabled send state while empty.\n *\n * Dependencies: metal-fx, lucide-react, @/lib/utils\n *\n * @example\n * <MetalPromptBar onSubmit={(text) => ask(text)} />\n */\n\n'use client';\n\nimport * as React from 'react';\nimport { MetalFx, type MetalFxPreset } from 'metal-fx';\nimport { ArrowUp, Paperclip } from 'lucide-react';\n\nimport { cn } from '@/lib/utils';\nimport { useSurfaceTheme, type SurfaceTheme } from '@/components/spectrumui/use-surface-theme';\n\nexport interface MetalPromptBarProps {\n  /** Placeholder for the empty composer. Default \"Build anything…\" */\n  placeholder?: string;\n  /** Pills shown bottom-left; each one reflects the metal ring in dark mode. Default [\"Agent\", \"Auto\"] */\n  chips?: string[];\n  /** Metal palette for the send ring. Default \"chromatic\" */\n  preset?: MetalFxPreset;\n  /** \"auto\" follows a `.dark`/`.light` class on <html>, then the OS. Default \"auto\" */\n  theme?: SurfaceTheme;\n  /** Fires with the trimmed text on Enter or the send button; the field clears afterwards */\n  onSubmit?: (text: string) => void;\n  /** Fires when a chip is clicked */\n  onChipClick?: (chip: string) => void;\n  /** Max textarea rows before it scrolls. Default 6 */\n  maxRows?: number;\n  className?: string;\n}\n\nexport function MetalPromptBar({\n  placeholder = 'Build anything…',\n  chips = ['Agent', 'Auto'],\n  preset = 'chromatic',\n  theme = 'auto',\n  onSubmit,\n  onChipClick,\n  maxRows = 6,\n  className,\n}: MetalPromptBarProps) {\n  const resolved = useSurfaceTheme(theme);\n  const [text, setText] = React.useState('');\n  const textareaRef = React.useRef<HTMLTextAreaElement>(null);\n  // Stable refs per chip so MetalFx can paint reflections onto them\n  const chipRefs = React.useMemo(\n    () => chips.map(() => React.createRef<HTMLButtonElement>()),\n    [chips],\n  );\n  const canSend = text.trim().length > 0;\n\n  const resize = (el: HTMLTextAreaElement) => {\n    el.style.height = '0px';\n    const line = parseFloat(getComputedStyle(el).lineHeight) || 24;\n    el.style.height = `${Math.min(el.scrollHeight, line * maxRows)}px`;\n  };\n\n  const submit = () => {\n    if (!canSend) return;\n    onSubmit?.(text.trim());\n    setText('');\n    const el = textareaRef.current;\n    if (el) {\n      el.value = '';\n      resize(el);\n    }\n  };\n\n  return (\n    <div\n      className={cn(\n        'w-full rounded-[22px] border border-black/8 bg-white p-3 shadow-[0_1px_2px_rgba(0,0,0,0.04),0_12px_32px_-12px_rgba(0,0,0,0.12)] dark:border-white/10 dark:bg-neutral-900 dark:shadow-[0_12px_32px_-12px_rgba(0,0,0,0.6)]',\n        className,\n      )}\n    >\n      <textarea\n        ref={textareaRef}\n        rows={1}\n        value={text}\n        placeholder={placeholder}\n        aria-label=\"Prompt\"\n        onChange={(event) => {\n          setText(event.target.value);\n          resize(event.target);\n        }}\n        onKeyDown={(event) => {\n          if (event.key === 'Enter' && !event.shiftKey && !event.nativeEvent.isComposing) {\n            event.preventDefault();\n            submit();\n          }\n        }}\n        className=\"block w-full resize-none bg-transparent px-1 pt-1 text-[15px] leading-6 text-neutral-900 outline-hidden placeholder:text-neutral-400 dark:text-neutral-100 dark:placeholder:text-neutral-500\"\n      />\n      <div className=\"mt-2 flex items-center gap-2\">\n        <button\n          type=\"button\"\n          aria-label=\"Attach\"\n          className=\"flex size-9 items-center justify-center rounded-full border border-black/8 text-neutral-600 transition-colors hover:bg-black/4 dark:border-white/10 dark:text-neutral-300 dark:hover:bg-white/6\"\n        >\n          <Paperclip className=\"size-4\" />\n        </button>\n        {chips.map((chip, index) => (\n          <button\n            key={chip}\n            ref={chipRefs[index]}\n            type=\"button\"\n            onClick={() => onChipClick?.(chip)}\n            className=\"h-9 rounded-full border border-black/8 px-3.5 text-[13px] font-medium text-neutral-700 transition-colors hover:bg-black/4 dark:border-white/10 dark:text-neutral-200 dark:hover:bg-white/6\"\n          >\n            {chip}\n          </button>\n        ))}\n        <span className=\"ms-auto hidden text-xs text-neutral-400 sm:block dark:text-neutral-500\">\n          Enter to send\n        </span>\n        <MetalFx\n          variant=\"circle\"\n          preset={preset}\n          theme={resolved}\n          reflectionTargets={chipRefs}\n          className={cn('inline-flex', !canSend && 'opacity-70')}\n        >\n          <button\n            type=\"button\"\n            aria-label=\"Send\"\n            disabled={!canSend}\n            onClick={submit}\n            className=\"flex size-9 items-center justify-center rounded-full text-neutral-900 transition-transform active:scale-95 disabled:cursor-not-allowed dark:text-white\"\n          >\n            <ArrowUp className=\"size-4\" />\n          </button>\n        </MetalFx>\n      </div>\n    </div>\n  );\n}\n",
      "type": "registry:component",
      "target": "components/spectrumui/metal-prompt-bar.tsx"
    }
  ],
  "type": "registry:component"
}
