{
  "name": "ChatMessage",
  "source": "src/components/ChatMessage.tsx",
  "propsType": "ChatMessageProps",
  "description": "ChatMessage — one turn in a transcript: who, when, what, and what can be\ndone with it.\n\nAN ARTICLE, NAMED BY ITS HEADER. Each message is an `<article>` labelled by\nits author and time, so a screen reader moves message to message and hears\n\"Ada Reyes 10:42\" before each. The avatar is decoration; the name says who.\n\nNOT A LIVE REGION. A thread that announced every message would read a\nstreaming answer out token by token — the reason StreamingText is not one\neither. Say when an answer is ready once, from the thread, the way the\nAssistantAnswer pattern does.\n\nIt holds a message; it does not send, stream or store one.",
  "import": "import { ChatMessage } from 'ionbase-ui';",
  "status": "stable",
  "summary": "One turn in a transcript — who, when, what, and what can be done with it. An article named by its author and time; never a live region.",
  "useWhen": [
    "a conversation with an assistant, shown as a thread of turns",
    "a transcript people read back — a support chat, a review thread between a person and an agent"
  ],
  "useInstead": [
    {
      "when": "the entries are changes to a record — who changed what, when",
      "use": "Timeline",
      "why": "that is history, read as an ordered list of events; a transcript is turns people and an assistant took"
    },
    {
      "when": "an agent is working through steps now",
      "use": "AgentActivity",
      "why": "a run has a live status per step; a message holds what was said"
    },
    {
      "when": "a system message tells the reader something went wrong or changed",
      "use": "Alert",
      "why": "an alert has an intent and a title; a message from a \"System\" author reads as a turn nobody took"
    }
  ],
  "composition": {
    "order": [
      "ChatMessage",
      "StreamingText",
      "Citation",
      "CitationList",
      "Alert"
    ],
    "note": "One ChatMessage per turn, in the order they were taken, oldest first. `from=\"person\"` for what a person typed, `from=\"assistant\"` for the reply. The assistant's content is the AssistantAnswer pattern: a StreamingText with Citations, then a CitationList and an Alert when degraded. `actions` follow the content — Copy, Ask again — as Buttons. Say when an answer is ready once, from a status region outside the messages, never from each message.",
    "example": "<ChatMessage from=\"person\" author=\"Ada Reyes\" avatar={<AvatarGradient size=\"sm\" initials=\"AR\" alt=\"Ada Reyes\" />} timestamp={askedAt}>What is our refund limit?</ChatMessage>\n<ChatMessage from=\"assistant\" author=\"Ionbase assistant\" avatar={<LogoMark size=\"sm\" label=\"Ionbase assistant\" />} timestamp={answeredAt} actions={<CopyButton value={text} label=\"Copy answer\" />}><StreamingText isStreaming={false}>…</StreamingText></ChatMessage>"
  },
  "variants": {
    "from": {
      "person": {
        "use": "what a person wrote — on the trailing side, in a muted bubble at most 80% across"
      },
      "assistant": {
        "use": "the assistant's reply — spans the column, since answers carry lists, sources and tables"
      }
    }
  },
  "slots": {
    "author": {
      "accepts": "text",
      "note": "the author's name, shown and read — the message's name starts with it"
    },
    "avatar": {
      "accepts": "Avatar, AvatarGradient, LogoMark",
      "note": "decoration, hidden from assistive tech; the name says who"
    },
    "children": {
      "accepts": "text, StreamingText, Citation, CitationList, Alert, Link",
      "note": "the message"
    },
    "actions": {
      "accepts": "Button, CopyButton",
      "note": "after the content, in reading order"
    }
  },
  "a11y": {
    "role": "article",
    "guarantees": [
      "each message is an `<article>` named by its header — the author, then the time — so a screen reader moves message to message and hears who and when first",
      "the time is a `<time>` with the exact instant as `dateTime`, whatever its label says",
      "the avatar is hidden from assistive tech",
      "it is not a live region: a thread never reads a streaming answer out as it arrives",
      "the actions come after the content in the DOM, so Tab reaches a source in the answer before Copy",
      "logical properties throughout, so right to left mirrors it"
    ],
    "requires": [
      "`author` on every message, a person's included — \"You\" at the least",
      "a status region outside the messages that says once when an answer is ready or incomplete"
    ],
    "notes": [
      "It renders on a server. It holds a message; it does not send, stream or store one."
    ]
  },
  "antiPatterns": [
    {
      "dont": "`role=\"log\"` or `aria-live` on the thread",
      "why": "a streaming answer is announced token by token, re-read with every chunk; announce completion once instead"
    },
    {
      "dont": "a person's message in the primary tint",
      "why": "the primary tint is AILabel's mark for generated content; a person's words must never read as generated"
    },
    {
      "dont": "a message with only an avatar to say who wrote it",
      "do": "`author` with the name",
      "why": "the avatar is hidden from assistive tech, so the message has no author for anyone who cannot see it"
    },
    {
      "dont": "a \"System\" message for an error or a notice",
      "do": "Alert",
      "why": "it reads as a turn in the conversation, and it has no intent to say whether anything is wrong"
    }
  ],
  "stylesheet": "src/styles/chat-message.css",
  "tokens": [
    "--border-width-default",
    "--font-family-sans",
    "--font-weight-semibold",
    "--radius-lg",
    "--spacing-12",
    "--spacing-4",
    "--spacing-8",
    "--surface-muted",
    "--text-default",
    "--text-secondary",
    "--type-body-sm",
    "--type-body-sm-line-height",
    "--type-caption",
    "--type-caption-line-height"
  ],
  "props": {
    "from": {
      "type": "ChatMessageFrom",
      "required": true,
      "origin": "own",
      "description": "Who wrote it. `person` is set apart — a tinted bubble on the trailing\nside — so a long thread reads as turns; `assistant` spans the column,\nsince its answers carry lists, sources and tables.",
      "values": [
        "person",
        "assistant"
      ]
    },
    "author": {
      "type": "React.ReactNode",
      "required": true,
      "origin": "own",
      "description": "The author's name, shown and read: \"Ada Reyes\", \"Ionbase assistant\"."
    },
    "avatar": {
      "type": "React.ReactNode",
      "required": false,
      "origin": "own",
      "description": "A picture for the author — Avatar, AvatarGradient, LogoMark. Hidden from\nassistive tech: the name beside it says who."
    },
    "timestamp": {
      "type": "string | Date | undefined",
      "required": false,
      "origin": "own",
      "description": "When it was sent. Rendered in a `<time>` with the exact instant."
    },
    "timestampLabel": {
      "type": "React.ReactNode",
      "required": false,
      "origin": "own",
      "description": "The text shown for the time — \"10:42\", \"2 min ago\" — in place of the\ndefault date and time."
    },
    "locale": {
      "type": "string | undefined",
      "required": false,
      "origin": "own",
      "description": "Locale for the default time label. Pass it when rendering on a server."
    },
    "timeZone": {
      "type": "string | undefined",
      "required": false,
      "origin": "own",
      "description": "Time zone for the default time label."
    },
    "children": {
      "type": "React.ReactNode",
      "required": true,
      "origin": "own",
      "description": "The message: text, StreamingText, Citations, a CitationList, an Alert."
    },
    "actions": {
      "type": "React.ReactNode",
      "required": false,
      "origin": "own",
      "description": "What can be done with it — Copy, Retry, feedback. Buttons, after the\ncontent, in reading order."
    }
  },
  "propCounts": {
    "own": 9,
    "aria": 0,
    "dom": 277,
    "other": 0
  }
}
