{
  "name": "ChatComposer",
  "package": "@magicblocksai/ui",
  "file": "packages/ui/src/components/ChatComposer.tsx",
  "chapterTag": "19 Conversation",
  "chapter": "19-conversation.html",
  "sectionId": "chat-transcript",
  "elName": "ChatTranscript",
  "demoUrl": "https://brand.magicblocks.ai/components/19-conversation#chat-transcript",
  "hasLiveDemo": false,
  "description": "Bottom-of-transcript composer — autogrowing textarea + Send button with\noptional attachment / action slots. Designed to live inside a\n`<ChatTranscript footer={...}>`, but works standalone.",
  "useClient": true,
  "interactivity": "interactive",
  "namedExports": [
    {
      "name": "ChatComposer",
      "isPrincipal": true,
      "isType": false
    },
    {
      "name": "ChatComposerProps",
      "isPrincipal": false,
      "isType": true
    }
  ],
  "importStatement": "import { ChatComposer } from \"@magicblocksai/ui\";",
  "props": [
    {
      "name": "value",
      "optional": true,
      "type": "string",
      "doc": "Controlled input value."
    },
    {
      "name": "defaultValue",
      "optional": true,
      "type": "string",
      "doc": "Uncontrolled initial value."
    },
    {
      "name": "onValueChange",
      "optional": true,
      "type": "(value: string) => void",
      "doc": "Fires with the input string."
    },
    {
      "name": "onSubmit",
      "optional": true,
      "type": "(value: string) => void",
      "doc": "Fires when the user submits (Enter without Shift, or clicks Send). Receives the current value. The composer does NOT clear itself — the consumer owns the value and decides when to clear."
    },
    {
      "name": "placeholder",
      "optional": true,
      "type": "string",
      "doc": "Placeholder for the textarea. Default `\"Type a message…\"`."
    },
    {
      "name": "disabled",
      "optional": true,
      "type": "boolean",
      "doc": "Disable the entire composer (input + send). Different from `sending`, which only disables the Send button."
    },
    {
      "name": "sending",
      "optional": true,
      "type": "boolean",
      "doc": "Pending state — disables Send and renders a spinner."
    },
    {
      "name": "sendLabel",
      "optional": true,
      "type": "ReactNode",
      "doc": "Render the Send button with this label. Default `\"Send\"`."
    },
    {
      "name": "attachments",
      "optional": true,
      "type": "ReactNode",
      "doc": "Left-side slot rendered before the textarea — typically an attachment button, emoji picker trigger, or `<SnippetTextarea>` style toolbar."
    },
    {
      "name": "actions",
      "optional": true,
      "type": "ReactNode",
      "doc": "Right-side slot rendered before the Send button — typically extra action icons (record, schedule, formatting toggles)."
    },
    {
      "name": "maxRows",
      "optional": true,
      "type": "number",
      "doc": "Maximum input rows the textarea grows to before scrolling. Default `6`."
    },
    {
      "name": "submitOnEnter",
      "optional": true,
      "type": "boolean",
      "doc": "Submit on Enter (Shift+Enter inserts a newline). Default `true`."
    },
    {
      "name": "helperText",
      "optional": true,
      "type": "ReactNode",
      "doc": "Optional helper text rendered beneath the input."
    }
  ],
  "classesUsed": [
    "chat-composer",
    "chat-composer-actions",
    "chat-composer-attachments",
    "chat-composer-helper",
    "chat-composer-input",
    "chat-composer-row",
    "chat-composer-send",
    "chat-composer-send-label",
    "chat-composer-spinner"
  ],
  "examples": {
    "react": null,
    "html": "<div class=\"chat-demo-frame\">\n          <div class=\"chat-transcript\">\n            <div class=\"chat-transcript-header\">\n              <strong>Spark CRM &middot; support</strong>\n              <span class=\"badge tone-success\">Live</span>\n            </div>\n            <div class=\"chat-transcript-scroll\" role=\"log\" aria-live=\"polite\" aria-relevant=\"additions\">\n              <div class=\"chat-transcript-list\">\n                <div class=\"chat-msg is-from-agent\">\n                  <div class=\"chat-msg-avatar\" aria-hidden=\"true\">SP</div>\n                  <div class=\"chat-msg-stack\">\n                    <div class=\"chat-msg-meta\">\n                      <span class=\"chat-msg-name\">Support agent</span>\n                      <span class=\"chat-msg-time\">09:14</span>\n                    </div>\n                    <div class=\"chat-msg-bubble-wrap\">\n                      <div class=\"chat-msg-bubble\">\n                        <div class=\"chat-msg-body\">Hi Hoang &mdash; what can I help with this morning?</div>\n                      </div>\n                    </div>\n                  </div>\n                </div>\n                <div class=\"chat-msg is-from-user\">\n                  <div class=\"chat-msg-avatar\" aria-hidden=\"true\">HT</div>\n                  <div class=\"chat-msg-stack\">\n                    <div class=\"chat-msg-meta\">\n                      <span class=\"chat-msg-time\">09:14</span>\n                    </div>\n                    <div class=\"chat-msg-bubble-wrap\">\n                      <div class=\"chat-msg-bubble\">\n                        <div class=\"chat-msg-body\">Hi &mdash; my password reset email never arrived. I tried twice last night.</div>\n                      </div>\n                    </div>\n                  </div>\n                </div>\n                <div class=\"chat-msg is-from-agent\">\n                  <div class=\"chat-msg-avatar\" aria-hidden=\"true\">SP</div>\n                  <div class=\"chat-msg-stack\">\n                    <div class=\"chat-msg-meta\">\n                      <span class=\"chat-msg-name\">Support agent</span>\n                      <span class=\"chat-msg-time\">09:15</span>\n                    </div>\n                    <div class=\"chat-msg-bubble-wrap\">\n                      <div class=\"chat-msg-bubble\">\n                        <div class=\"chat-msg-body\">Let me check the delivery log. One moment.</div>\n                      </div>\n                    </div>\n                  </div>\n                </div>\n                <div class=\"chat-msg is-from-system\" role=\"status\">\n                  <div class=\"chat-msg-system-line\">\n                    Tool call &middot; mailgun.search\n                    <span class=\"chat-msg-system-time\">09:15</span>\n                  </div>\n                </div>\n                <div class=\"chat-msg is-from-agent\">\n                  <div class=\"chat-msg-avatar\" aria-hidden=\"true\">SP</div>\n                  <div class=\"chat-msg-stack\">\n                    <div class=\"chat-msg-meta\">\n                      <span class=\"chat-msg-name\">Support agent</span>\n                      <span class=\"chat-msg-time\">09:16</span>\n                    </div>\n                    <div class=\"chat-msg-bubble-wrap\">\n                      <div class=\"chat-msg-bubble\">\n                        <div class=\"chat-msg-body\">Found it &mdash; both attempts hit a Gmail spam filter at your domain. I&rsquo;ve resent through our backup route. It should arrive in under a minute.</div>\n                      </div>\n                    </div>\n                  </div>\n                </div>\n                <div class=\"chat-msg is-from-user\">\n                  <div class=\"chat-msg-avatar\" aria-hidden=\"true\">HT</div>\n                  <div class=\"chat-msg-stack\">\n                    <div class=\"chat-msg-meta\">\n                      <span class=\"chat-msg-time\">09:17</span>\n                    </div>\n                    <div class=\"chat-msg-bubble-wrap\">\n                      <div class=\"chat-msg-bubble\">\n                        <div class=\"chat-msg-body\">Got it. Thank you!</div>\n                      </div>\n                    </div>\n                  </div>\n                </div>\n              </div>\n            </div>\n            <div class=\"chat-transcript-footer\">\n              <form class=\"chat-composer\">\n                <div class=\"chat-composer-row\">\n                  <textarea class=\"chat-composer-input\" rows=\"1\" placeholder=\"Reply to Hoang&hellip;\" aria-label=\"Message\"></textarea>\n                  <button type=\"submit\" class=\"chat-composer-send\" disabled aria-label=\"Send\"><span class=\"chat-composer-send-label\">Send</span></button>\n                </div>\n              </form>\n            </div>\n          </div>\n        </div>",
    "css": ".chat-composer { display: flex; flex-direction: column; gap: 4px; }\n\n.chat-composer-actions {\n  display: inline-flex;\n  align-items: center;\n  gap: 2px;\n}\n\n.chat-composer-attachments {\n  display: inline-flex;\n  align-items: center;\n  gap: 2px;\n}\n\n.chat-composer-helper {\n  font: 400 11.5px/1.4 var(--f-body);\n  color: var(--fg-faint);\n  padding: 0 var(--s-2);\n}\n\n.chat-composer-input {\n  flex: 1;\n  appearance: none;\n  background: transparent;\n  border: 0;\n  outline: none;\n  resize: none;\n  padding: 6px 0;\n  min-height: 24px;\n  font: 400 14px/1.4 var(--f-body);\n  color: var(--fg);\n  overflow-y: hidden;\n}\n\n.chat-composer-row {\n  display: flex;\n  align-items: flex-end;\n  gap: 6px;\n  padding: 6px 6px 6px 10px;\n  border: 1px solid var(--hair);\n  border-radius: var(--r-md);\n  background: var(--bg-paper);\n  transition: border-color var(--dur-2) var(--ease),\n              box-shadow var(--dur-2) var(--ease);\n}\n\n.chat-composer-send {\n  appearance: none;\n  display: inline-flex;\n  align-items: center;\n  justify-content: center;\n  gap: 4px;\n  height: 32px;\n  padding: 0 12px;\n  border: 0;\n  border-radius: var(--r-sm);\n  background: var(--accent);\n  color: var(--paper);\n  font: 500 13px/1 var(--f-body);\n  cursor: pointer;\n  transition: filter var(--dur-2) var(--ease);\n}\n\n.chat-composer-send-label { line-height: 1; }\n\n.chat-composer-spinner {\n  width: 14px;\n  height: 14px;\n  border-radius: 999px;\n  border: 1.5px solid currentColor;\n  border-right-color: transparent;\n  animation: chat-composer-spin 0.7s linear infinite;\n}"
  }
}
