{
  "name": "ChatMessage",
  "package": "@magicblocksai/ui",
  "file": "packages/ui/src/components/ChatMessage.tsx",
  "chapterTag": "16 Pipeline & CRM",
  "chapter": "16-app-pipeline.html",
  "sectionId": "session-page",
  "elName": "SessionPage",
  "demoUrl": "https://brand.magicblocks.ai/components/16-app-pipeline#session-page",
  "hasLiveDemo": false,
  "description": "One conversation bubble — agent / user / system. The atom that\n`<ChatTranscript>` arranges into a stack.",
  "useClient": true,
  "interactivity": "interactive",
  "namedExports": [
    {
      "name": "ChatMessage",
      "isPrincipal": true,
      "isType": false
    },
    {
      "name": "ChatMessageProps",
      "isPrincipal": false,
      "isType": true
    },
    {
      "name": "ChatMessageFrom",
      "isPrincipal": false,
      "isType": false
    },
    {
      "name": "ChatMessageStatus",
      "isPrincipal": false,
      "isType": false
    },
    {
      "name": "ChatMessageConfidence",
      "isPrincipal": false,
      "isType": false
    },
    {
      "name": "ChatReaction",
      "isPrincipal": false,
      "isType": false
    }
  ],
  "importStatement": "import { ChatMessage } from \"@magicblocksai/ui\";",
  "props": [
    {
      "name": "from",
      "optional": false,
      "type": "ChatMessageFrom",
      "doc": "Which side of the conversation."
    },
    {
      "name": "name",
      "optional": true,
      "type": "ReactNode",
      "doc": "Sender display name."
    },
    {
      "name": "avatar",
      "optional": true,
      "type": "ReactNode",
      "doc": "Avatar slot — letter/initials, image, or rendered element."
    },
    {
      "name": "timestamp",
      "optional": true,
      "type": "ReactNode",
      "doc": "Timestamp text — pre-formatted by the consumer."
    },
    {
      "name": "reactions",
      "optional": true,
      "type": "ChatReaction[]",
      "doc": "Reaction chips rendered beneath the bubble. Pass an empty array to render no reactions and no slot."
    },
    {
      "name": "actions",
      "optional": true,
      "type": "ReactNode",
      "doc": "Hover-revealed action slot (top-right of the bubble). Typically a `<MessageTraceButton>` + copy / more icons. Stays visible on touch / coarse pointers."
    },
    {
      "name": "status",
      "optional": true,
      "type": "ChatMessageStatus",
      "doc": "Streaming / failed / sent state. `streaming` adds an animated cursor after the body; `failed` paints a red rail and adds an alert role."
    },
    {
      "name": "confidence",
      "optional": true,
      "type": "ChatMessageConfidence",
      "doc": "Optional confidence dot rendered next to the timestamp — kit colour coding: high = success, medium = warning, low = error."
    },
    {
      "name": "density",
      "optional": true,
      "type": "\"comfortable\" | \"compact\"",
      "doc": "Compact density (used inside dense inboxes or sidebar previews)."
    },
    {
      "name": "children",
      "optional": true,
      "type": "ReactNode",
      "doc": "Message body."
    }
  ],
  "classesUsed": [
    "alert",
    "chat-msg",
    "chat-msg-actions",
    "chat-msg-avatar",
    "chat-msg-body",
    "chat-msg-bubble",
    "chat-msg-bubble-wrap",
    "chat-msg-caret",
    "chat-msg-confidence",
    "chat-msg-failed-note",
    "chat-msg-human",
    "chat-msg-meta",
    "chat-msg-name",
    "chat-msg-reaction",
    "chat-msg-reaction-count",
    "chat-msg-reaction-emoji",
    "chat-msg-reactions",
    "chat-msg-stack",
    "chat-msg-system-line",
    "chat-msg-system-time",
    "chat-msg-time",
    "title"
  ],
  "examples": {
    "react": null,
    "html": "<div class=\"session-page\" style=\"max-width:820px;\">\n  <div class=\"sp-topbar\"><a class=\"sp-back\" href=\"#sessions\">&lsaquo; Sessions</a><div class=\"sp-nav\"><button type=\"button\" class=\"sp-navbtn\">&lsaquo; Prev</button><button type=\"button\" class=\"sp-navbtn\">Next &rsaquo;</button></div></div>\n  <div class=\"sp-hero\">\n    <div class=\"sp-hero-top\">\n      <span class=\"sp-avatar\" aria-hidden=\"true\">SK</span>\n      <div class=\"sp-hero-id\">\n        <h2 class=\"sp-name\"><span class=\"sp-sdot\" data-sentiment=\"positive\" aria-hidden=\"true\"></span>Sarah Kim<span class=\"sp-company\"> &middot; Skyhook</span></h2>\n        <div class=\"sp-meta\"><span class=\"channel-chip\" data-channel=\"webchat\">Webchat</span><span>Sage agent &middot; v2.3</span><span>Apr 28, 9:15 AM</span><span>#S-4821</span></div>\n      </div>\n      <span class=\"sp-status\">Completed</span>\n    </div>\n    <div class=\"sp-hero-foot\">\n      <div class=\"sp-goals\"><div class=\"sp-goals-k\">Goals achieved</div><div class=\"sp-goals-chips\"><span class=\"sp-goal\">Qualified</span><span class=\"sp-goal\">Meeting booked</span></div></div>\n      <div class=\"sp-stats\"><div class=\"sp-stat\"><div class=\"sp-stat-k\">Duration</div><div class=\"sp-stat-v\">4m 12s</div></div><div class=\"sp-stat\"><div class=\"sp-stat-k\">Messages</div><div class=\"sp-stat-v\">18</div></div><div class=\"sp-stat\"><div class=\"sp-stat-k\">Sentiment</div><div class=\"sp-stat-v\">Positive</div></div></div>\n    </div>\n  </div>\n  <div class=\"session-summary-band sp-band\">\n    <div class=\"ssb-summary\">\n      <div class=\"ssb-summary-eb\">AI summary<span class=\"ssb-tag\">SAGE</span></div>\n      <p class=\"ssb-summary-text\">Sarah from Skyhook asked about 5-seat volume pricing for a CS team moving handoffs to Slack. Sage confirmed the Scale plan, qualified the use case, and booked a walkthrough.</p>\n    </div>\n    <div class=\"ssb-cards\">\n      <div class=\"ssb-card\">\n        <div class=\"ssb-card-eb\">Key facts</div>\n        <div class=\"key-fact-grid\" data-layout=\"list\">\n          <div class=\"kfg-row\"><span class=\"kfg-key\">seats</span><span class=\"kfg-val\">5</span></div>\n          <div class=\"kfg-row\"><span class=\"kfg-key\">plan</span><span class=\"kfg-val\">Scale</span></div>\n          <div class=\"kfg-row\"><span class=\"kfg-key\">handoff</span><span class=\"kfg-val\">Slack</span></div>\n        </div>\n      </div>\n      <div class=\"ssb-card\">\n        <div class=\"ssb-card-eb\">Memories</div>\n        <div class=\"memory-list\">\n          <div class=\"memory-row\"><div class=\"memory-body\"><div class=\"memory-text\">Prefers Slack for team handoffs</div><div class=\"memory-meta\"><span class=\"memory-source\">this session</span><span class=\"memory-conf\" data-conf=\"high\">high</span></div></div></div>\n          <div class=\"memory-row\"><div class=\"memory-body\"><div class=\"memory-text\">Evaluating for a 5-person CS team</div><div class=\"memory-meta\"><span class=\"memory-source\">this session</span><span class=\"memory-conf\" data-conf=\"high\">high</span></div></div></div>\n        </div>\n        <button type=\"button\" class=\"ssb-expand\">Expand all memories (5)</button>\n      </div>\n      <div class=\"ssb-card\">\n        <div class=\"ssb-card-eb\">Handover &amp; outcome</div>\n        <div class=\"handover-outcome\">\n          <div class=\"ho-row\" data-kind=\"webhook\"><span class=\"ho-ic\" aria-hidden=\"true\"></span><div class=\"ho-body\"><span class=\"ho-label\">CRM lead created</span><span class=\"ho-detail\">POST crm.acme.com/leads</span></div><span class=\"ho-status\">200</span></div>\n          <div class=\"ho-row\" data-kind=\"handover\"><span class=\"ho-ic\" aria-hidden=\"true\"></span><div class=\"ho-body\"><span class=\"ho-label\">Handed to journey block</span><span class=\"ho-detail\">Post-demo nurture</span></div></div>\n        </div>\n      </div>\n    </div>\n  </div>\n  <div class=\"sp-transcript\"><button type=\"button\" class=\"sp-tcollapse\" aria-expanded=\"false\"><span class=\"sp-tcollapse-chevron\" aria-hidden=\"true\"></span>Show transcript<span class=\"sp-tcollapse-count\">18</span></button></div>\n</div>",
    "css": ".alert {\n  display: flex; gap: var(--s-3);\n  padding: var(--s-4);\n  background: var(--bg-paper);\n  border: 1px solid var(--hair);\n  border-left: 3px solid var(--success);\n  border-radius: var(--r-md);\n}\n\n.chat-msg {\n  display: grid;\n  /* minmax(0, 1fr) (not 1fr) so the bubble track can shrink below its\n     content's min-content — otherwise word-break:break-word collapses the\n     bubble to one character per line in a narrow container (e.g. a ~340px\n     test rail). */\n  grid-template-columns: 32px minmax(0, 1fr);\n  gap: var(--s-3);\n  margin: 0;\n  padding: 0 var(--s-4);\n}\n\n.chat-msg-actions {\n  position: absolute;\n  top: -8px;\n  right: 4px;\n  display: inline-flex;\n  align-items: center;\n  gap: 2px;\n  padding: 2px;\n  background: var(--bg-paper);\n  border: 1px solid var(--hair);\n  border-radius: 999px;\n  box-shadow: 0 2px 8px color-mix(in oklab, var(--ink) 10%, transparent);\n  opacity: 0;\n  transition: opacity var(--dur-2) var(--ease);\n}\n\n.chat-msg-avatar {\n  width: 32px;\n  height: 32px;\n  border-radius: 999px;\n  display: inline-flex;\n  align-items: center;\n  justify-content: center;\n  background: var(--bg-warm);\n  color: var(--fg);\n  font: 600 12px/1 var(--f-mono);\n  flex-shrink: 0;\n  overflow: hidden;\n}\n\n.chat-msg-body { white-space: pre-wrap; }\n\n.chat-msg-bubble {\n  padding: 10px 14px;\n  font: 400 14px/1.5 var(--f-body);\n  background: var(--bg-warm);\n  color: var(--fg);\n  border-radius: 16px 16px 16px 4px;\n  word-break: break-word;\n  position: relative;\n}\n\n.chat-msg-bubble-wrap {\n  position: relative;\n  display: inline-flex;\n  max-width: min(560px, 80%);\n}\n\n.chat-msg-caret {\n  display: inline-block;\n  width: 2px;\n  height: 1em;\n  background: currentColor;\n  margin-left: 2px;\n  vertical-align: text-bottom;\n  animation: chat-msg-caret-blink 1s steps(2, end) infinite;\n}\n\n.chat-msg-confidence {\n  width: 8px;\n  height: 8px;\n  border-radius: 999px;\n  background: var(--fg-faint);\n  display: inline-block;\n}\n\n.chat-msg-failed-note {\n  font: 400 11.5px/1.3 var(--f-body);\n  color: var(--error-text, #8B2417);\n  margin-top: 2px;\n}\n\n.chat-msg-human {\n  font: 600 11px/1 var(--f-body);\n  color: var(--accent);\n  background: color-mix(in oklab, var(--accent) 12%, transparent);\n  padding: 2px 6px;\n  border-radius: 999px;\n  letter-spacing: 0.02em;\n}\n\n.chat-msg-meta {\n  display: inline-flex;\n  align-items: baseline;\n  gap: 6px;\n  color: var(--fg-soft);\n  font: 400 11.5px/1 var(--f-body);\n}\n\n.chat-msg-name {\n  font: 500 12.5px/1 var(--f-body);\n  color: var(--fg);\n}\n\n.chat-msg-reaction {\n  appearance: none;\n  display: inline-flex;\n  align-items: center;\n  gap: 4px;\n  padding: 2px 8px;\n  border-radius: 999px;\n  background: var(--bg-paper);\n  border: 1px solid var(--hair);\n  font: 500 11.5px/1 var(--f-body);\n  color: var(--fg);\n  cursor: pointer;\n  transition: background var(--dur-2) var(--ease),\n              border-color var(--dur-2) var(--ease);\n}\n\n.chat-msg-reaction-count { font-variant-numeric: tabular-nums; }\n\n.chat-msg-reaction-emoji { line-height: 1; font-size: 13px; }\n\n.chat-msg-reactions {\n  display: inline-flex;\n  flex-wrap: wrap;\n  gap: 4px;\n  margin-top: 2px;\n}\n\n.chat-msg-stack {\n  display: flex;\n  flex-direction: column;\n  gap: 4px;\n  min-width: 0;\n}\n\n.chat-msg-system-line {\n  display: inline-flex;\n  align-items: center;\n  gap: 6px;\n  padding: 4px 10px;\n  border-radius: 999px;\n  background: var(--bg-warm);\n  font: 400 11.5px/1.3 var(--f-body);\n  color: var(--fg-soft);\n}\n\n.chat-msg-system-time {\n  font: 400 10.5px/1 var(--f-mono);\n  color: var(--fg-faint);\n  margin-left: 4px;\n}\n\n.chat-msg-time {\n  font: 400 11px/1 var(--f-mono);\n  color: var(--fg-faint);\n  font-variant-numeric: tabular-nums;\n}\n\n.title { font: 700 32px/1.15 var(--f-display); letter-spacing: -0.015em; margin: 0; }"
  }
}
